swift
variantprivate.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_VARIANT_PRIVATE_H
7 #define SWIFT_MISC_VARIANT_PRIVATE_H
8 
9 #include <stdexcept>
10 
11 #include <QDBusArgument>
12 #include <QDBusMetaType>
13 #include <QJsonObject>
14 #include <QMetaType>
15 #include <QString>
16 
17 #include "misc/inheritancetraits.h"
18 #include "misc/propertyindexref.h"
19 #include "misc/swiftmiscexport.h"
20 
21 namespace swift::misc
22 {
23  class CEmpty;
24  class CVariant;
25  class CPropertyIndexRef;
26  class CIcon;
27 
28  template <typename T>
29  class CSequence;
30 
31  template <typename T>
32  void registerMetaValueType();
33 
34  namespace private_ns
35  {
37  struct SWIFT_MISC_EXPORT IValueObjectMetaInfo
38  {
39  virtual ~IValueObjectMetaInfo() = default;
40  virtual QString toQString(const void *object, bool i18n) const = 0;
41  virtual QJsonObject toJson(const void *object) const = 0;
42  virtual void convertFromJson(const QJsonObject &json, void *object) const = 0;
43  virtual QJsonObject toMemoizedJson(const void *object) const = 0;
44  virtual void convertFromMemoizedJson(const QJsonObject &json, void *object,
45  bool allowFallbackToJson) const = 0;
46  virtual void unmarshall(const QDBusArgument &arg, void *object) const = 0;
47  virtual size_t getValueHash(const void *object) const = 0;
48  virtual int getMetaTypeId() const = 0;
49  virtual const void *upCastTo(const void *object, int metaTypeId) const = 0;
50  virtual int compareImpl(const void *lhs, const void *rhs) const = 0;
51  virtual void setPropertyByIndex(void *object, const QVariant &variant, CPropertyIndexRef index) const = 0;
52  virtual void propertyByIndex(const void *object, QVariant &o_variant,
53  swift::misc::CPropertyIndexRef index) const = 0;
54  virtual bool equalsPropertyByIndex(const void *object, const QVariant &compareValue,
55  CPropertyIndexRef index) const = 0;
56  virtual bool matches(const void *object, const CVariant &value) const = 0;
57  virtual int toIcon(const void *object) const = 0;
58  };
59 
61  class CVariantException : public std::invalid_argument
62  {
63  public:
64  template <class T>
65  CVariantException(const T &, const QString &opName) : CVariantException(qMetaTypeId<T>(), opName)
66  {}
67 
68  CVariantException(int typeId, const QString &opName)
69  : std::invalid_argument((blurb(typeId, opName)).toStdString()), m_operationName(opName)
70  {}
71 
72  const QString &operationName() const { return m_operationName; }
73 
74  ~CVariantException() {}
75 
76  private:
77  QString m_operationName;
78 
79  static QString blurb(int typeId, const QString &operationName)
80  {
81  return QString("CVariant requested unsupported operation of contained ") + QMetaType::typeName(typeId) +
82  " object: " + operationName;
83  }
84  };
85 
87  struct CValueObjectMetaInfoHelper
88  {
89  template <typename T>
90  static QJsonObject toJson(const T &object, decltype(static_cast<void>(object.toJson()), 0))
91  {
92  return object.toJson();
93  }
94  template <typename T>
95  static QJsonObject toJson(const T &object, ...)
96  {
97  throw CVariantException(object, "toJson");
98  }
99 
100  template <typename T>
101  static void convertFromJson(const QJsonObject &json, T &object,
102  decltype(static_cast<void>(object.convertFromJson(json)), 0))
103  {
104  object.convertFromJson(json);
105  }
106  template <typename T>
107  static void convertFromJson(const QJsonObject &, T &object, ...)
108  {
109  throw CVariantException(object, "convertFromJson");
110  }
111 
112  template <typename T>
113  static QJsonObject toMemoizedJson(const T &object, decltype(static_cast<void>(object.toMemoizedJson()), 0))
114  {
115  return object.toMemoizedJson();
116  }
117  template <typename T>
118  static QJsonObject toMemoizedJson(const T &object, ...)
119  {
120  return toJson(object, 0);
121  }
122 
123  template <typename T>
124  static void convertFromMemoizedJson(
125  const QJsonObject &json, T &object, bool allowFallbackToJson,
126  decltype(static_cast<void>(object.convertFromMemoizedJson(json, allowFallbackToJson)), 0))
127  {
128  object.convertFromMemoizedJson(json, allowFallbackToJson);
129  }
130  template <typename T>
131  static void convertFromMemoizedJson(const QJsonObject &json, T &object, bool allowFallbackToJson, ...)
132  {
133  convertFromJson(json, object, 0);
134  Q_UNUSED(allowFallbackToJson)
135  }
136 
137  template <typename T>
138  static size_t getValueHash(const T &object, decltype(static_cast<void>(qHash(object)), 0))
139  {
140  return qHash(object);
141  }
142  template <typename T>
143  static size_t getValueHash(const T &object, ...)
144  {
145  throw CVariantException(object, "getValueHash");
146  }
147 
148  template <typename T>
149  static int compareImpl(const T &lhs, const T &rhs, decltype(static_cast<void>(compare(lhs, rhs)), 0))
150  {
151  return compare(lhs, rhs);
152  }
153  template <typename T>
154  static int compareImpl(const T &lhs, const T &, ...)
155  {
156  throw CVariantException(lhs, "compare");
157  }
158 
159  template <typename T>
160  static void setPropertyByIndex(T &object, const QVariant &variant, CPropertyIndexRef index,
161  decltype(static_cast<void>(object.setPropertyByIndex(index, variant)), 0))
162  {
163  object.setPropertyByIndex(index, variant);
164  }
165  template <typename T>
166  static void setPropertyByIndex(T &object, const QVariant &, CPropertyIndexRef, ...)
167  {
168  throw CVariantException(object, "setPropertyByIndex");
169  }
170 
171  template <typename T>
172  static void propertyByIndex(QVariant &o_variant, const T &object, CPropertyIndexRef index,
173  decltype(static_cast<void>(object.propertyByIndex(index)), 0))
174  {
175  o_variant = object.propertyByIndex(index);
176  }
177  template <typename T>
178  static void propertyByIndex(QVariant &, const T &object, CPropertyIndexRef, ...)
179  {
180  throw CVariantException(object, "propertyByIndex");
181  }
182 
183  template <typename T>
184  static bool equalsPropertyByIndex(const T &object, const QVariant &variant, CPropertyIndexRef index,
185  decltype(static_cast<void>(object.equalsPropertyByIndex(variant, index)),
186  0))
187  {
188  return object.equalsPropertyByIndex(variant, index);
189  }
190  template <typename T>
191  static bool equalsPropertyByIndex(const T &object, const QVariant &, CPropertyIndexRef, ...)
192  {
193  throw CVariantException(object, "equalsPropertyByIndex");
194  }
195 
196  template <typename T>
197  static int
198  toIcon(const T &object,
199  std::enable_if_t<!std::is_same_v<T, CVariant>, decltype(static_cast<void>(object.toIcon()), 0)>)
200  {
201  return object.toIcon();
202  }
203  template <typename T>
204  static int toIcon(const T &object, ...)
205  {
206  throw CVariantException(object, "toIcon");
207  }
208 
209  template <typename T>
210  static bool matches(const T &object, const CVariant &value,
211  decltype(static_cast<void>(object.matches(value)), 0))
212  {
213  return object.matches(value);
214  }
215  template <typename T>
216  static bool matches(const T &object, const CVariant &, ...)
217  {
218  throw CVariantException(object, "matches");
219  }
220  };
221 
223  template <typename T>
224  struct CValueObjectMetaInfo : public IValueObjectMetaInfo
225  {
226  CValueObjectMetaInfo();
227  virtual ~CValueObjectMetaInfo() override;
228  static CValueObjectMetaInfo *instance(const T &);
229 
230  CValueObjectMetaInfo(const CValueObjectMetaInfo &) = delete;
231  CValueObjectMetaInfo &operator=(const CValueObjectMetaInfo &) = delete;
232 
233  virtual QString toQString(const void *object, bool i18n) const override;
234  virtual QJsonObject toJson(const void *object) const override;
235  virtual void convertFromJson(const QJsonObject &json, void *object) const override;
236  virtual QJsonObject toMemoizedJson(const void *object) const override;
237  virtual void convertFromMemoizedJson(const QJsonObject &json, void *object,
238  bool allowFallbackToJson) const override;
239  virtual void unmarshall(const QDBusArgument &arg, void *object) const override;
240  virtual size_t getValueHash(const void *object) const override;
241  virtual int getMetaTypeId() const override;
242  virtual const void *upCastTo(const void *object, int metaTypeId) const override;
243  virtual int compareImpl(const void *lhs, const void *rhs) const override;
244  virtual void setPropertyByIndex(void *object, const QVariant &variant,
245  CPropertyIndexRef index) const override;
246  virtual void propertyByIndex(const void *object, QVariant &o_variant,
247  swift::misc::CPropertyIndexRef index) const override;
248  virtual bool equalsPropertyByIndex(const void *object, const QVariant &compareValue,
249  CPropertyIndexRef index) const override;
250  virtual int toIcon(const void *object) const override;
251  virtual bool matches(const void *object, const CVariant &value) const override;
252 
253  static const T &cast(const void *object);
254  static T &cast(void *object);
255  };
256 
257  template <typename T>
258  CValueObjectMetaInfo<T>::CValueObjectMetaInfo()
259  {}
260  template <typename T>
261  CValueObjectMetaInfo<T>::~CValueObjectMetaInfo()
262  {}
263  template <typename T>
264  CValueObjectMetaInfo<T> *CValueObjectMetaInfo<T>::instance(const T &)
265  {
266  static CValueObjectMetaInfo mi;
267  return &mi;
268  }
269  template <typename T>
270  QString CValueObjectMetaInfo<T>::toQString(const void *object, bool i18n) const
271  {
272  return cast(object).toQString(i18n);
273  }
274  template <typename T>
275  QJsonObject CValueObjectMetaInfo<T>::toJson(const void *object) const
276  {
277  return CValueObjectMetaInfoHelper::toJson(cast(object), 0);
278  }
279  template <typename T>
280  void CValueObjectMetaInfo<T>::convertFromJson(const QJsonObject &json, void *object) const
281  {
282  CValueObjectMetaInfoHelper::convertFromJson(json, cast(object), 0);
283  }
284  template <typename T>
285  QJsonObject CValueObjectMetaInfo<T>::toMemoizedJson(const void *object) const
286  {
287  return CValueObjectMetaInfoHelper::toMemoizedJson(cast(object), 0);
288  }
289  template <typename T>
290  void CValueObjectMetaInfo<T>::convertFromMemoizedJson(const QJsonObject &json, void *object,
291  bool allowFallbackToJson) const
292  {
293  CValueObjectMetaInfoHelper::convertFromMemoizedJson(json, cast(object), allowFallbackToJson, 0);
294  }
295  template <typename T>
296  void CValueObjectMetaInfo<T>::unmarshall(const QDBusArgument &arg, void *object) const
297  {
298  arg >> cast(object);
299  }
300  template <typename T>
301  size_t CValueObjectMetaInfo<T>::getValueHash(const void *object) const
302  {
303  return CValueObjectMetaInfoHelper::getValueHash(cast(object), 0);
304  }
305  template <typename T>
306  int CValueObjectMetaInfo<T>::getMetaTypeId() const
307  {
308  if constexpr (QMetaTypeId<T>::Defined) { return qMetaTypeId<T>(); }
309  else { return QMetaType::UnknownType; }
310  }
311  template <typename T>
312  const void *CValueObjectMetaInfo<T>::upCastTo(const void *object, int metaTypeId) const
313  {
314  if constexpr (THasMetaBaseV<T>)
315  {
316  const auto base = static_cast<const void *>(static_cast<const TMetaBaseOfT<T> *>(&cast(object)));
317  return metaTypeId == getMetaTypeId() ?
318  object :
319  CValueObjectMetaInfo<TMetaBaseOfT<T>>::instance(cast(object))->upCastTo(base, metaTypeId);
320  }
321  else
322  {
323  Q_UNUSED(metaTypeId);
324  return object;
325  }
326  }
327  template <typename T>
328  int CValueObjectMetaInfo<T>::compareImpl(const void *lhs, const void *rhs) const
329  {
330  return CValueObjectMetaInfoHelper::compareImpl(cast(lhs), cast(rhs), 0);
331  }
332  template <typename T>
333  void CValueObjectMetaInfo<T>::setPropertyByIndex(void *object, const QVariant &variant,
334  CPropertyIndexRef index) const
335  {
336  CValueObjectMetaInfoHelper::setPropertyByIndex(cast(object), variant, index, 0);
337  }
338  template <typename T>
339  void CValueObjectMetaInfo<T>::propertyByIndex(const void *object, QVariant &o_variant,
340  swift::misc::CPropertyIndexRef index) const
341  {
342  CValueObjectMetaInfoHelper::propertyByIndex(o_variant, cast(object), index, 0);
343  }
344  template <typename T>
345  bool CValueObjectMetaInfo<T>::equalsPropertyByIndex(const void *object, const QVariant &compareValue,
346  CPropertyIndexRef index) const
347  {
348  return CValueObjectMetaInfoHelper::equalsPropertyByIndex(cast(object), compareValue, index, 0);
349  }
350  template <typename T>
351  int CValueObjectMetaInfo<T>::toIcon(const void *object) const
352  {
353  return CValueObjectMetaInfoHelper::toIcon(cast(object), 0);
354  }
355  template <typename T>
356  bool CValueObjectMetaInfo<T>::matches(const void *object, const CVariant &value) const
357  {
358  return CValueObjectMetaInfoHelper::matches(cast(object), value, 0);
359  }
360  template <typename T>
361  const T &CValueObjectMetaInfo<T>::cast(const void *object)
362  {
363  return *static_cast<const T *>(object);
364  }
365  template <typename T>
366  T &CValueObjectMetaInfo<T>::cast(void *object)
367  {
368  return *static_cast<T *>(object);
369  }
370 
372  IValueObjectMetaInfo *getValueObjectMetaInfo(int typeId);
373 
375  IValueObjectMetaInfo *getValueObjectMetaInfo(const QVariant &);
376 
378  template <typename T>
379  IValueObjectMetaInfo *getValueObjectMetaInfo()
380  {
381  return getValueObjectMetaInfo(qMetaTypeId<T>());
382  }
383 
385  template <typename T, typename = std::enable_if_t<std::is_base_of_v<CSequence<typename T::value_type>, T> &&
386  !std::is_same_v<typename T::value_type, CVariant>>>
387  constexpr bool canConvertVariantList(int)
388  {
389  return true;
390  }
391  template <typename T>
392  constexpr bool canConvertVariantList(...)
393  {
394  return false;
395  }
396 
397  template <typename T>
398  struct MetaTypeHelper
399  {
400  static constexpr int maybeGetMetaTypeId()
401  {
402  if constexpr (QMetaTypeId<T>::Defined) { return qMetaTypeId<T>(); }
403  else { return QMetaType::UnknownType; }
404  }
405  static void maybeRegisterMetaType();
406  static void maybeRegisterMetaList();
407  };
408 
409  template <typename T>
410  void MetaTypeHelper<T>::maybeRegisterMetaType()
411  {
412  if constexpr (QMetaTypeId<T>::Defined)
413  {
414  qRegisterMetaType<T>();
415  qDBusRegisterMetaType<T>();
416  registerMetaValueType<T>();
417  maybeRegisterMetaList();
418  }
419  };
421  } // namespace private_ns
422 } // namespace swift::misc
423 
424 Q_DECLARE_METATYPE(swift::misc::private_ns::IValueObjectMetaInfo *)
425 
426 #endif // SWIFT_MISC_VARIANT_PRIVATE_H
Non-owning reference to a CPropertyIndex with a subset of its features.
int compare(T a, T b)
Compare arithmetic values.
size_t qHash(const std::string &key, uint seed)
std::string qHash
Definition: metaclass.h:86
Free functions in swift::misc.
void registerMetaValueType()
This registers the value type T with the swift::misc:: meta type system, making it available for use ...
Definition: variant.h:46
#define SWIFT_MISC_EXPORT
Export a class or function from the library.