// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include #include #include #include #include #include #if !QT_CONFIG(protobuf_unsafe_registry) # include #endif #include QT_BEGIN_NAMESPACE /*! \relates QtProtobuf \fn template = true> inline void qRegisterProtobufType() Registers a Protobuf type \e T. This function is normally called by generated code. */ /*! \relates QtProtobuf \fn template = true> inline void qRegisterProtobufMapType(); Registers a Protobuf map type \c K and \c V. \c V must be a QProtobufMessage. This function is normally called by generated code. */ /*! \relates QtProtobuf \fn template ::value, bool> = true> inline void qRegisterProtobufEnumType(); Registers serializers for enumeration type \c T in QtProtobuf global serializers registry. This function is normally called by generated code. */ namespace { std::vector ®isterFunctions() { // no need for implicit sharing etc, so stick with std::vector static std::vector registrationList; return registrationList; } template void registerBasicConverters() { QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); if constexpr (!std::is_same_v) { QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); } QMetaType::registerConverter(T::fromType); QMetaType::registerConverter(T::toType); QMetaType::registerConverter(T::toString); } static void qRegisterBaseTypes() { [[maybe_unused]] // definitely unused static bool registered = [] { qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); registerBasicConverters(); registerBasicConverters(); registerBasicConverters(); registerBasicConverters(); registerBasicConverters(); registerBasicConverters(); return true; }(); } /* \internal \brief The HandlersRegistry is a container to store mapping between metatype identifier and serialization handlers. */ struct HandlersRegistry { void registerHandler(QMetaType type, QtProtobufPrivate::Serializer serializer, QtProtobufPrivate::Deserializer deserializer) { #if !QT_CONFIG(protobuf_unsafe_registry) QWriteLocker locker(&m_lock); #endif m_registry[type] = { serializer, deserializer }; } QtProtobufPrivate::SerializationHandler findHandler(QMetaType type) { #if !QT_CONFIG(protobuf_unsafe_registry) QReadLocker locker(&m_lock); #endif auto it = m_registry.constFind(type); if (it != m_registry.constEnd()) return it.value(); return {}; } private: # if !QT_CONFIG(protobuf_unsafe_registry) QReadWriteLock m_lock; # endif QHash m_registry; }; Q_GLOBAL_STATIC(HandlersRegistry, handlersRegistry) Q_CONSTINIT QBasicMutex registerMutex; } void QtProtobufPrivate::registerHandler(QMetaType type, Serializer serializer, Deserializer deserializer) { handlersRegistry->registerHandler(type, serializer, deserializer); } QtProtobufPrivate::SerializationHandler QtProtobufPrivate::findHandler(QMetaType type) { if (!handlersRegistry.exists()) return {}; return handlersRegistry->findHandler(type); } namespace QtProtobuf { ProtoTypeRegistrar::ProtoTypeRegistrar(QtProtobuf::RegisterFunction initializer) { std::scoped_lock lock(registerMutex); registerFunctions().push_back(initializer); } } /*! \relates QtProtobuf Calling this function registers all, currently known, protobuf types with the serializer registry. \note Only since Qt 6.6.3 version you don't have to call this function manually, as it is called automatically. For earlier versions it's better to call it before serialization/deserialization attempt. */ void qRegisterProtobufTypes() { qRegisterBaseTypes(); std::scoped_lock lock(registerMutex); std::vector registrationList; registrationList.swap(registerFunctions()); for (QtProtobuf::RegisterFunction registerFunc : registrationList) registerFunc(); } /*! \class template = true> class QtProtobufPrivate::ListIterator \internal */ /*! \class template = true> class QtProtobufPrivate::MapIterator \internal */ /*! \struct QtProtobufPrivate::SerializationHandler \internal \brief SerializationHandlers contains set of objects that are required for class serialization/deserialization. */ QT_END_NAMESPACE