metawriters.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #ifndef QTJSONSERIALIZER_METAWRITERS_H
  2. #define QTJSONSERIALIZER_METAWRITERS_H
  3. #include "qtjsonserializer_global.h"
  4. #include <QtCore/qmetatype.h>
  5. #include <QtCore/qvariant.h>
  6. #include <QtCore/qsharedpointer.h>
  7. #include <QtCore/qhash.h>
  8. #include <QtCore/qreadwritelock.h>
  9. #include <QtCore/qset.h>
  10. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  11. #include <QtCore/qlinkedlist.h>
  12. #endif
  13. namespace QtJsonSerializer::MetaWriters {
  14. class SequentialWriterFactory;
  15. //! The writer class for sequential containers
  16. class Q_JSONSERIALIZER_EXPORT SequentialWriter
  17. {
  18. Q_DISABLE_COPY(SequentialWriter)
  19. public:
  20. //! Information about a sequential container
  21. struct SequenceInfo {
  22. //! The containers data type
  23. int type = QMetaType::UnknownType;
  24. //! Specifies if the container is a finite set
  25. bool isSet = false;
  26. };
  27. //! Registers a container factory for the given container and value classes
  28. template <template<typename> class TContainer, typename TClass>
  29. static void registerWriter();
  30. //! @copybrief SequentialWriter::registerWriter()
  31. static void registerWriter(int metaTypeId, SequentialWriterFactory *factory);
  32. //! Checks if a writer exists for the given type
  33. static bool canWrite(int metaTypeId);
  34. //! Returns a writer instance for the given data, or nullptr if none found
  35. static QSharedPointer<SequentialWriter> getWriter(QVariant &data);
  36. //! Returns the information details of the given type
  37. static SequenceInfo getInfo(int metaTypeId);
  38. virtual ~SequentialWriter();
  39. //! Return the information for the wrapped container
  40. virtual SequenceInfo info() const = 0;
  41. //! Reserves space for size elements in the container
  42. virtual void reserve(int size) = 0;
  43. //! Adds an element to the "end" of the container
  44. virtual void add(const QVariant &value) = 0;
  45. protected:
  46. //! @private
  47. SequentialWriter();
  48. };
  49. //! A factory to create sequential writer instances from variant data
  50. class Q_JSONSERIALIZER_EXPORT SequentialWriterFactory
  51. {
  52. Q_DISABLE_COPY(SequentialWriterFactory)
  53. public:
  54. SequentialWriterFactory();
  55. virtual ~SequentialWriterFactory();
  56. //! Factory method to create the instance. data can be null for read-only writers
  57. virtual QSharedPointer<SequentialWriter> create(void *data) const = 0;
  58. };
  59. class AssociativeWriterFactory;
  60. //! The writer class for associative containers
  61. class Q_JSONSERIALIZER_EXPORT AssociativeWriter
  62. {
  63. Q_DISABLE_COPY(AssociativeWriter)
  64. public:
  65. //! Information about a associative container
  66. struct AssociationInfo {
  67. //! The type of the associations keys
  68. int keyType = QMetaType::UnknownType;
  69. //! The type of the associations values
  70. int valueType = QMetaType::UnknownType;
  71. };
  72. //! Registers a container factory for the given container, key and value classes
  73. template <template<typename, typename> class TContainer, typename TKey, typename TValue>
  74. static void registerWriter();
  75. //! @copybrief AssociativeWriter::registerWriter()
  76. static void registerWriter(int metaTypeId, AssociativeWriterFactory *factory);
  77. //! Checks if a writer exists for the given type
  78. static bool canWrite(int metaTypeId);
  79. //! Returns a writer instance for the given data, or nullptr if none found
  80. static QSharedPointer<AssociativeWriter> getWriter(QVariant &data);
  81. //! Returns the information details of the given type
  82. static AssociationInfo getInfo(int metaTypeId);
  83. virtual ~AssociativeWriter();
  84. //! Return the information for the wrapped container
  85. virtual AssociationInfo info() const = 0;
  86. //! Inserts the given value for the given key into the container
  87. virtual void add(const QVariant &key, const QVariant &value) = 0;
  88. protected:
  89. //! @private
  90. AssociativeWriter();
  91. };
  92. //! A factory to create associative writer instances from variant data
  93. class Q_JSONSERIALIZER_EXPORT AssociativeWriterFactory
  94. {
  95. Q_DISABLE_COPY(AssociativeWriterFactory)
  96. public:
  97. AssociativeWriterFactory();
  98. virtual ~AssociativeWriterFactory();
  99. //! Factory method to create the instance. data can be null for read-only writers
  100. virtual QSharedPointer<AssociativeWriter> create(void *data) const = 0;
  101. };
  102. // ------------- Generic Implementation classes -------------
  103. namespace Implementations {
  104. template <template<typename> class TContainer, typename TClass>
  105. class SequentialWriterImpl final : public SequentialWriter
  106. {
  107. public:
  108. SequentialWriterImpl(TContainer<TClass> *data)
  109. : _data{data}
  110. {}
  111. SequenceInfo info() const final {
  112. return {qMetaTypeId<TClass>(), false};
  113. }
  114. void reserve(int size) final {
  115. _data->reserve(size);
  116. }
  117. void add(const QVariant &value) final {
  118. _data->append(value.template value<TClass>());
  119. }
  120. private:
  121. TContainer<TClass> *_data;
  122. };
  123. template <template<typename> class TContainer, typename TClass>
  124. class SequentialWriterFactoryImpl final : public SequentialWriterFactory
  125. {
  126. public:
  127. QSharedPointer<SequentialWriter> create(void *data) const final {
  128. return QSharedPointer<SequentialWriterImpl<TContainer, TClass>>::create(reinterpret_cast<TContainer<TClass>*>(data));
  129. }
  130. };
  131. template <template<typename, typename> class TContainer, typename TKey, typename TValue>
  132. class AssociativeWriterImpl final : public AssociativeWriter
  133. {
  134. public:
  135. AssociativeWriterImpl(TContainer<TKey, TValue> *data)
  136. : _data{data}
  137. {}
  138. AssociationInfo info() const final {
  139. return {qMetaTypeId<TKey>(), qMetaTypeId<TValue>()};
  140. }
  141. void add(const QVariant &key, const QVariant &value) final {
  142. _data->insert(key.template value<TKey>(),
  143. value.template value<TValue>());
  144. }
  145. private:
  146. TContainer<TKey, TValue> *_data;
  147. };
  148. template <template<typename, typename> class TContainer, typename TKey, typename TValue>
  149. class AssociativeWriterFactoryImpl final : public AssociativeWriterFactory
  150. {
  151. public:
  152. QSharedPointer<AssociativeWriter> create(void *data) const final {
  153. return QSharedPointer<AssociativeWriterImpl<TContainer, TKey, TValue>>::create(reinterpret_cast<TContainer<TKey, TValue>*>(data));
  154. }
  155. };
  156. // ------------- Specializations and base generic implementations -------------
  157. template <typename TClass>
  158. class SequentialWriterImpl<QSet, TClass> final : public SequentialWriter
  159. {
  160. public:
  161. SequentialWriterImpl(QSet<TClass> *data)
  162. : _data{data}
  163. {}
  164. SequenceInfo info() const final {
  165. return {qMetaTypeId<TClass>(), true};
  166. }
  167. void reserve(int size) final {
  168. _data->reserve(size);
  169. }
  170. void add(const QVariant &value) final {
  171. _data->insert(value.template value<TClass>());
  172. }
  173. private:
  174. QSet<TClass> *_data;
  175. };
  176. #if !defined(QT_NO_LINKED_LIST) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
  177. template <typename TClass>
  178. class SequentialWriterImpl<QLinkedList, TClass> final : public SequentialWriter
  179. {
  180. public:
  181. SequentialWriterImpl(QLinkedList<TClass> *data)
  182. : _data{data}
  183. {}
  184. SequenceInfo info() const final {
  185. return {qMetaTypeId<TClass>(), false};
  186. }
  187. void reserve(int) final {}
  188. void add(const QVariant &value) final {
  189. _data->append(value.template value<TClass>());
  190. }
  191. private:
  192. QLinkedList<TClass> *_data;
  193. };
  194. #endif
  195. template <>
  196. class SequentialWriterImpl<QList, QVariant> final : public SequentialWriter
  197. {
  198. public:
  199. SequentialWriterImpl(QVariantList *data);
  200. SequenceInfo info() const final;
  201. void reserve(int size) final;
  202. void add(const QVariant &value) final;
  203. private:
  204. QVariantList *_data;
  205. };
  206. template <>
  207. class AssociativeWriterImpl<QMap, QString, QVariant> final : public AssociativeWriter
  208. {
  209. public:
  210. AssociativeWriterImpl(QVariantMap *data);
  211. AssociationInfo info() const final;
  212. void add(const QVariant &key, const QVariant &value) final;
  213. private:
  214. QVariantMap *_data;
  215. };
  216. template <>
  217. class AssociativeWriterImpl<QHash, QString, QVariant> final : public AssociativeWriter
  218. {
  219. public:
  220. AssociativeWriterImpl(QVariantHash *data);
  221. AssociationInfo info() const final;
  222. void add(const QVariant &key, const QVariant &value) final;
  223. private:
  224. QVariantHash *_data;
  225. };
  226. }
  227. template<template<typename> class TContainer, typename TClass>
  228. void SequentialWriter::registerWriter()
  229. {
  230. registerWriter(qMetaTypeId<TContainer<TClass>>(),
  231. new Implementations::SequentialWriterFactoryImpl<TContainer, TClass>{});
  232. }
  233. template<template<typename, typename> class TContainer, typename TKey, typename TValue>
  234. void AssociativeWriter::registerWriter()
  235. {
  236. registerWriter(qMetaTypeId<TContainer<TKey, TValue>>(),
  237. new Implementations::AssociativeWriterFactoryImpl<TContainer, TKey, TValue>{});
  238. }
  239. }
  240. #endif // QTJSONSERIALIZER_METAWRITERS_H