#ifndef QTJSONSERIALIZER_METAWRITERS_H #define QTJSONSERIALIZER_METAWRITERS_H #include "qtjsonserializer_global.h" #include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #include #endif namespace QtJsonSerializer::MetaWriters { class SequentialWriterFactory; //! The writer class for sequential containers class Q_JSONSERIALIZER_EXPORT SequentialWriter { Q_DISABLE_COPY(SequentialWriter) public: //! Information about a sequential container struct SequenceInfo { //! The containers data type int type = QMetaType::UnknownType; //! Specifies if the container is a finite set bool isSet = false; }; //! Registers a container factory for the given container and value classes template class TContainer, typename TClass> static void registerWriter(); //! @copybrief SequentialWriter::registerWriter() static void registerWriter(int metaTypeId, SequentialWriterFactory *factory); //! Checks if a writer exists for the given type static bool canWrite(int metaTypeId); //! Returns a writer instance for the given data, or nullptr if none found static QSharedPointer getWriter(QVariant &data); //! Returns the information details of the given type static SequenceInfo getInfo(int metaTypeId); virtual ~SequentialWriter(); //! Return the information for the wrapped container virtual SequenceInfo info() const = 0; //! Reserves space for size elements in the container virtual void reserve(int size) = 0; //! Adds an element to the "end" of the container virtual void add(const QVariant &value) = 0; protected: //! @private SequentialWriter(); }; //! A factory to create sequential writer instances from variant data class Q_JSONSERIALIZER_EXPORT SequentialWriterFactory { Q_DISABLE_COPY(SequentialWriterFactory) public: SequentialWriterFactory(); virtual ~SequentialWriterFactory(); //! Factory method to create the instance. data can be null for read-only writers virtual QSharedPointer create(void *data) const = 0; }; class AssociativeWriterFactory; //! The writer class for associative containers class Q_JSONSERIALIZER_EXPORT AssociativeWriter { Q_DISABLE_COPY(AssociativeWriter) public: //! Information about a associative container struct AssociationInfo { //! The type of the associations keys int keyType = QMetaType::UnknownType; //! The type of the associations values int valueType = QMetaType::UnknownType; }; //! Registers a container factory for the given container, key and value classes template class TContainer, typename TKey, typename TValue> static void registerWriter(); //! @copybrief AssociativeWriter::registerWriter() static void registerWriter(int metaTypeId, AssociativeWriterFactory *factory); //! Checks if a writer exists for the given type static bool canWrite(int metaTypeId); //! Returns a writer instance for the given data, or nullptr if none found static QSharedPointer getWriter(QVariant &data); //! Returns the information details of the given type static AssociationInfo getInfo(int metaTypeId); virtual ~AssociativeWriter(); //! Return the information for the wrapped container virtual AssociationInfo info() const = 0; //! Inserts the given value for the given key into the container virtual void add(const QVariant &key, const QVariant &value) = 0; protected: //! @private AssociativeWriter(); }; //! A factory to create associative writer instances from variant data class Q_JSONSERIALIZER_EXPORT AssociativeWriterFactory { Q_DISABLE_COPY(AssociativeWriterFactory) public: AssociativeWriterFactory(); virtual ~AssociativeWriterFactory(); //! Factory method to create the instance. data can be null for read-only writers virtual QSharedPointer create(void *data) const = 0; }; // ------------- Generic Implementation classes ------------- namespace Implementations { template class TContainer, typename TClass> class SequentialWriterImpl final : public SequentialWriter { public: SequentialWriterImpl(TContainer *data) : _data{data} {} SequenceInfo info() const final { return {qMetaTypeId(), false}; } void reserve(int size) final { _data->reserve(size); } void add(const QVariant &value) final { _data->append(value.template value()); } private: TContainer *_data; }; template class TContainer, typename TClass> class SequentialWriterFactoryImpl final : public SequentialWriterFactory { public: QSharedPointer create(void *data) const final { return QSharedPointer>::create(reinterpret_cast*>(data)); } }; template class TContainer, typename TKey, typename TValue> class AssociativeWriterImpl final : public AssociativeWriter { public: AssociativeWriterImpl(TContainer *data) : _data{data} {} AssociationInfo info() const final { return {qMetaTypeId(), qMetaTypeId()}; } void add(const QVariant &key, const QVariant &value) final { _data->insert(key.template value(), value.template value()); } private: TContainer *_data; }; template class TContainer, typename TKey, typename TValue> class AssociativeWriterFactoryImpl final : public AssociativeWriterFactory { public: QSharedPointer create(void *data) const final { return QSharedPointer>::create(reinterpret_cast*>(data)); } }; // ------------- Specializations and base generic implementations ------------- template class SequentialWriterImpl final : public SequentialWriter { public: SequentialWriterImpl(QSet *data) : _data{data} {} SequenceInfo info() const final { return {qMetaTypeId(), true}; } void reserve(int size) final { _data->reserve(size); } void add(const QVariant &value) final { _data->insert(value.template value()); } private: QSet *_data; }; #if !defined(QT_NO_LINKED_LIST) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) template class SequentialWriterImpl final : public SequentialWriter { public: SequentialWriterImpl(QLinkedList *data) : _data{data} {} SequenceInfo info() const final { return {qMetaTypeId(), false}; } void reserve(int) final {} void add(const QVariant &value) final { _data->append(value.template value()); } private: QLinkedList *_data; }; #endif template <> class SequentialWriterImpl final : public SequentialWriter { public: SequentialWriterImpl(QVariantList *data); SequenceInfo info() const final; void reserve(int size) final; void add(const QVariant &value) final; private: QVariantList *_data; }; template <> class AssociativeWriterImpl final : public AssociativeWriter { public: AssociativeWriterImpl(QVariantMap *data); AssociationInfo info() const final; void add(const QVariant &key, const QVariant &value) final; private: QVariantMap *_data; }; template <> class AssociativeWriterImpl final : public AssociativeWriter { public: AssociativeWriterImpl(QVariantHash *data); AssociationInfo info() const final; void add(const QVariant &key, const QVariant &value) final; private: QVariantHash *_data; }; } template class TContainer, typename TClass> void SequentialWriter::registerWriter() { registerWriter(qMetaTypeId>(), new Implementations::SequentialWriterFactoryImpl{}); } template class TContainer, typename TKey, typename TValue> void AssociativeWriter::registerWriter() { registerWriter(qMetaTypeId>(), new Implementations::AssociativeWriterFactoryImpl{}); } } #endif // QTJSONSERIALIZER_METAWRITERS_H