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() override = default;
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(typeId).name() +
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  ~CValueObjectMetaInfo() override;
228  static CValueObjectMetaInfo *instance(const T &);
229 
230  CValueObjectMetaInfo(const CValueObjectMetaInfo &) = delete;
231  CValueObjectMetaInfo &operator=(const CValueObjectMetaInfo &) = delete;
232 
233  QString toQString(const void *object, bool i18n) const override;
234  QJsonObject toJson(const void *object) const override;
235  void convertFromJson(const QJsonObject &json, void *object) const override;
236  QJsonObject toMemoizedJson(const void *object) const override;
237  void convertFromMemoizedJson(const QJsonObject &json, void *object,
238  bool allowFallbackToJson) const override;
239  void unmarshall(const QDBusArgument &arg, void *object) const override;
240  size_t getValueHash(const void *object) const override;
241  int getMetaTypeId() const override;
242  const void *upCastTo(const void *object, int metaTypeId) const override;
243  int compareImpl(const void *lhs, const void *rhs) const override;
244  void setPropertyByIndex(void *object, const QVariant &variant, CPropertyIndexRef index) const override;
245  void propertyByIndex(const void *object, QVariant &o_variant,
246  swift::misc::CPropertyIndexRef index) const override;
247  bool equalsPropertyByIndex(const void *object, const QVariant &compareValue,
248  CPropertyIndexRef index) const override;
249  int toIcon(const void *object) const override;
250  bool matches(const void *object, const CVariant &value) const override;
251 
252  static const T &cast(const void *object);
253  static T &cast(void *object);
254  };
255 
256  template <typename T>
257  CValueObjectMetaInfo<T>::CValueObjectMetaInfo() = default;
258  template <typename T>
259  CValueObjectMetaInfo<T>::~CValueObjectMetaInfo() = default;
260  template <typename T>
261  CValueObjectMetaInfo<T> *CValueObjectMetaInfo<T>::instance(const T &)
262  {
263  static CValueObjectMetaInfo mi;
264  return &mi;
265  }
266  template <typename T>
267  QString CValueObjectMetaInfo<T>::toQString(const void *object, bool i18n) const
268  {
269  return cast(object).toQString(i18n);
270  }
271  template <typename T>
272  QJsonObject CValueObjectMetaInfo<T>::toJson(const void *object) const
273  {
274  return CValueObjectMetaInfoHelper::toJson(cast(object), 0);
275  }
276  template <typename T>
277  void CValueObjectMetaInfo<T>::convertFromJson(const QJsonObject &json, void *object) const
278  {
279  CValueObjectMetaInfoHelper::convertFromJson(json, cast(object), 0);
280  }
281  template <typename T>
282  QJsonObject CValueObjectMetaInfo<T>::toMemoizedJson(const void *object) const
283  {
284  return CValueObjectMetaInfoHelper::toMemoizedJson(cast(object), 0);
285  }
286  template <typename T>
287  void CValueObjectMetaInfo<T>::convertFromMemoizedJson(const QJsonObject &json, void *object,
288  bool allowFallbackToJson) const
289  {
290  CValueObjectMetaInfoHelper::convertFromMemoizedJson(json, cast(object), allowFallbackToJson, 0);
291  }
292  template <typename T>
293  void CValueObjectMetaInfo<T>::unmarshall(const QDBusArgument &arg, void *object) const
294  {
295  arg >> cast(object);
296  }
297  template <typename T>
298  size_t CValueObjectMetaInfo<T>::getValueHash(const void *object) const
299  {
300  return CValueObjectMetaInfoHelper::getValueHash(cast(object), 0);
301  }
302  template <typename T>
303  int CValueObjectMetaInfo<T>::getMetaTypeId() const
304  {
305  if constexpr (QMetaTypeId<T>::Defined) { return qMetaTypeId<T>(); }
306  else { return QMetaType::UnknownType; }
307  }
308  template <typename T>
309  const void *CValueObjectMetaInfo<T>::upCastTo(const void *object, int metaTypeId) const
310  {
311  if constexpr (THasMetaBaseV<T>)
312  {
313  const auto base = static_cast<const void *>(static_cast<const TMetaBaseOfT<T> *>(&cast(object)));
314  return metaTypeId == getMetaTypeId() ?
315  object :
316  CValueObjectMetaInfo<TMetaBaseOfT<T>>::instance(cast(object))->upCastTo(base, metaTypeId);
317  }
318  else
319  {
320  Q_UNUSED(metaTypeId);
321  return object;
322  }
323  }
324  template <typename T>
325  int CValueObjectMetaInfo<T>::compareImpl(const void *lhs, const void *rhs) const
326  {
327  return CValueObjectMetaInfoHelper::compareImpl(cast(lhs), cast(rhs), 0);
328  }
329  template <typename T>
330  void CValueObjectMetaInfo<T>::setPropertyByIndex(void *object, const QVariant &variant,
331  CPropertyIndexRef index) const
332  {
333  CValueObjectMetaInfoHelper::setPropertyByIndex(cast(object), variant, index, 0);
334  }
335  template <typename T>
336  void CValueObjectMetaInfo<T>::propertyByIndex(const void *object, QVariant &o_variant,
337  swift::misc::CPropertyIndexRef index) const
338  {
339  CValueObjectMetaInfoHelper::propertyByIndex(o_variant, cast(object), index, 0);
340  }
341  template <typename T>
342  bool CValueObjectMetaInfo<T>::equalsPropertyByIndex(const void *object, const QVariant &compareValue,
343  CPropertyIndexRef index) const
344  {
345  return CValueObjectMetaInfoHelper::equalsPropertyByIndex(cast(object), compareValue, index, 0);
346  }
347  template <typename T>
348  int CValueObjectMetaInfo<T>::toIcon(const void *object) const
349  {
350  return CValueObjectMetaInfoHelper::toIcon(cast(object), 0);
351  }
352  template <typename T>
353  bool CValueObjectMetaInfo<T>::matches(const void *object, const CVariant &value) const
354  {
355  return CValueObjectMetaInfoHelper::matches(cast(object), value, 0);
356  }
357  template <typename T>
358  const T &CValueObjectMetaInfo<T>::cast(const void *object)
359  {
360  return *static_cast<const T *>(object);
361  }
362  template <typename T>
363  T &CValueObjectMetaInfo<T>::cast(void *object)
364  {
365  return *static_cast<T *>(object);
366  }
367 
369  IValueObjectMetaInfo *getValueObjectMetaInfo(QMetaType mt);
370 
372  IValueObjectMetaInfo *getValueObjectMetaInfo(const QVariant &);
373 
375  template <typename T>
376  IValueObjectMetaInfo *getValueObjectMetaInfo()
377  {
378  return getValueObjectMetaInfo(qMetaTypeId<T>());
379  }
380 
382  template <typename T, typename = std::enable_if_t<std::is_base_of_v<CSequence<typename T::value_type>, T> &&
383  !std::is_same_v<typename T::value_type, CVariant>>>
384  constexpr bool canConvertVariantList(int)
385  {
386  return true;
387  }
388  template <typename T>
389  constexpr bool canConvertVariantList(...)
390  {
391  return false;
392  }
393 
394  template <typename T>
395  struct MetaTypeHelper
396  {
397  static constexpr int maybeGetMetaTypeId()
398  {
399  if constexpr (QMetaTypeId<T>::Defined) { return qMetaTypeId<T>(); }
400  else { return QMetaType::UnknownType; }
401  }
402  static void maybeRegisterMetaType();
403  static void maybeRegisterMetaList();
404  };
405 
406  template <typename T>
407  void MetaTypeHelper<T>::maybeRegisterMetaType()
408  {
409  if constexpr (QMetaTypeId<T>::Defined)
410  {
411  qRegisterMetaType<T>();
412  qDBusRegisterMetaType<T>();
413  registerMetaValueType<T>();
414  maybeRegisterMetaList();
415  }
416  };
418  } // namespace private_ns
419 } // namespace swift::misc
420 
421 Q_DECLARE_METATYPE(swift::misc::private_ns::IValueObjectMetaInfo *)
422 
423 #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:84
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
const char * name() const const
#define SWIFT_MISC_EXPORT
Export a class or function from the library.