Nuria Framework - Core
Core module of the NuriaProject Framework
 All Classes Functions Typedefs Enumerations Enumerator Groups
variant.hpp
1 /* Copyright (c) 2014, The Nuria Project
2  * This software is provided 'as-is', without any express or implied
3  * warranty. In no event will the authors be held liable for any damages
4  * arising from the use of this software.
5  * Permission is granted to anyone to use this software for any purpose,
6  * including commercial applications, and to alter it and redistribute it
7  * freely, subject to the following restrictions:
8  * 1. The origin of this software must not be misrepresented; you must not
9  * claim that you wrote the original software. If you use this software
10  * in a product, an acknowledgment in the product documentation would be
11  * appreciated but is not required.
12  * 2. Altered source versions must be plainly marked as such, and must not be
13  * misrepresented as being the original software.
14  * 3. This notice may not be removed or altered from any source
15  * distribution.
16  */
17 
18 #ifndef NURIA_VARIANT_HPP
19 #define NURIA_VARIANT_HPP
20 
21 #include "essentials.hpp"
22 #include <QStringList>
23 #include <QMetaType>
24 #include <QVariant>
25 
26 namespace Nuria {
27 class VariantIteratorPrivate;
28 
112 class NURIA_CORE_EXPORT Variant {
113 public:
114 
118  typedef bool (*Comparison)(const void *, const void *);
119 
123  typedef void *(*Conversion)(const void *);
124 
125  // Destructor
126  typedef void (*IteratorDtorFunc)(void *);
127 
128  // Copy constructor
129  typedef void *(*IteratorCopyFunc)(void *);
130 
131  // For value() and key()
132  typedef QVariant (*IteratorValueFunc)(void *, int);
133 
134  // For operator++ and operator--
135  typedef void (*IteratorIncFunc)(void *);
136 
137  // For operator+ and operator-
138  typedef void *(*IteratorMoveFunc)(void *, int);
139 
140  // For operator-(Iterator)
141  typedef int (*IteratorDistanceFunc)(void *, void *);
142 
143  // For begin and end
144  typedef void *(*IteratorStartEndFunc)(void *);
145 
146  // For operator==
147  typedef bool (*IteratorComparisonFunc)(void *, void *);
148 
149  // For count()
150  typedef int (*IteratorCountFunc)(void *);
151 
152  // For find()
153  typedef void *(*IteratorFindFunc)(void *, const QVariant &);
154 
159  static bool equal (const QVariant &left, const QVariant &right);
160  static bool notEqual (const QVariant &left, const QVariant &right);
161 
162  static bool lessThan (const QVariant &left, const QVariant &right);
163  static bool greaterThan (const QVariant &left, const QVariant &right);
164 
165  static bool lessEqualThan (const QVariant &left, const QVariant &right);
166  static bool greaterEqualThan (const QVariant &left, const QVariant &right);
167 
178  inline static bool canCompare (const QVariant &left, const QVariant &right)
179  { return canCompare (left.userType (), right.userType ()); }
180 
184  inline static bool canCompare (const QVariant &left, int rightType)
185  { return canCompare (left.userType (), rightType); }
186 
190  template< typename Right > inline static bool canCompare (const QVariant &left)
191  { return canCompare (left.userType (), qMetaTypeId< Right > ()); }
192 
196  template< typename Left, typename Right > inline static bool canCompare ()
197  { return canCompare (qMetaTypeId< Left > (), qMetaTypeId< Right > ()); }
198 
202  static bool canCompare (int leftType, int rightType);
203 
215  static QVariant convert (const QVariant &variant, int type);
216 
220  template< typename T > static QVariant convert (const QVariant &variant)
221  { return convert (variant, qMetaTypeId< T > ()); }
222 
236  template< typename T > inline static bool canConvert (const QVariant &variant)
237  { return canConvert (variant.userType (), qMetaTypeId< T > ()); }
238 
243  inline static bool canConvert (const QVariant &variant, int toType)
244  { return canConvert (variant.userType (), toType); }
245 
249  static bool canConvert (int fromType, int toType);
250 
257  template< typename T > static T toValue (const QVariant &variant) {
258  QVariant result = convert (variant, qMetaTypeId< T > ());
259 
260  if (result.isValid ()) {
261  return result.value< T > ();
262  }
263 
264  return T ();
265  }
266 
279  template< typename T > inline static void registerType ()
280  { registerType< T, T > (); }
281 
287  template< typename T, typename Right > inline static void registerType () {
288  typedef bool(T::*Func)(const Right &) const;
289  Func equal = &T::operator==;
290  Func less = &T::operator<;
291  registerType (qMetaTypeId< T > (), qMetaTypeId< Right > (),
292  (Comparison)equal, (Comparison)less);
293  }
294 
302  static void registerType (int type, int rightType, Comparison equal, Comparison lessThan);
303 
309  static void registerType (int type, int rightType, Comparison equal, Comparison notEqual,
310  Comparison less, Comparison greater, Comparison lessEqual,
311  Comparison greaterEqual);
312 
320  template< typename From, typename To >
321  static void registerConversion (To *(*func)(const From &))
322  { registerConversion (qMetaTypeId< From > (), qMetaTypeId< To > (), (Conversion)func); }
323 
334  template< typename From, typename To >
335  static void registerConversion () {
336  auto func = &autoConvTempl< From, To >;
337  registerConversion (qMetaTypeId< From > (), qMetaTypeId< To > (), (Conversion)func);
338  }
339 
345  static void registerConversion (int from, int to, Conversion func);
346 
351  template< typename T >
352  static void registerIterators (typename T::mapped_type *a = (typename T::mapped_type *)0) {
353  Q_UNUSED(a)
354  int keyType = qMetaTypeId< typename T::key_type > ();
355  int valueType = qMetaTypeId< typename T::mapped_type > ();
356 
357  registerIterator (qMetaTypeId< T > (), valueType, keyType,
358  (IteratorDtorFunc)&iteratorDtor< T >,
359  (IteratorCopyFunc)&iteratorCopy< T >,
360  (IteratorStartEndFunc)&iteratorBegin< T >,
361  (IteratorStartEndFunc)&iteratorEnd< T >,
362  (IteratorIncFunc)&iteratorNext< T >,
363  (IteratorIncFunc)&iteratorPrev< T >,
364  (IteratorMoveFunc)&iteratorMove< T >,
365  (IteratorDistanceFunc)&iteratorDistance< T >,
366  (IteratorValueFunc)&iteratorValue< T >,
367  (IteratorValueFunc)&iteratorKey< T >,
368  (IteratorComparisonFunc)&iteratorEqual< T >,
369  (IteratorCountFunc)&iteratorCount< T >,
370  (IteratorFindFunc)&iteratorFindMap< T, typename T::key_type >);
371 
372  }
373 
378  template< typename T >
379  static void registerIterators (typename T::value_type *a = (typename T::value_type *)0) {
380  Q_UNUSED(a)
381  int valueType = qMetaTypeId< typename T::value_type > ();
382 
383  registerIterator (qMetaTypeId< T > (), valueType, 0,
384  (IteratorDtorFunc)&iteratorDtor< T >,
385  (IteratorCopyFunc)&iteratorCopy< T >,
386  (IteratorStartEndFunc)&iteratorBegin< T >,
387  (IteratorStartEndFunc)&iteratorEnd< T >,
388  (IteratorIncFunc)&iteratorNext< T >,
389  (IteratorIncFunc)&iteratorPrev< T >,
390  (IteratorMoveFunc)&iteratorMove< T >,
391  (IteratorDistanceFunc)&iteratorDistance< T >,
392  (IteratorValueFunc)&iteratorValue< T >,
393  0,
394  (IteratorComparisonFunc)&iteratorEqual< T >,
395  (IteratorCountFunc)&iteratorCount< T >,
396  (IteratorFindFunc)&iteratorFindList< T, typename T::value_type >);
397 
398  }
399 
407  class NURIA_CORE_EXPORT Iterator {
408  public:
409 
414  Iterator ();
415  Iterator (const Iterator &other);
416  ~Iterator ();
417 
418  bool isValid () const;
419 
420  const Iterator &operator= (const Iterator &other);
421 
422  bool operator== (const Iterator &other) const;
423  inline bool operator!= (const Iterator &other) const
424  { return !(*this == other); }
425 
426  Iterator &operator++ ();
427  inline Iterator &operator++ (int) { return operator++ (); }
428 
429  Iterator &operator-- ();
430  inline Iterator &operator-- (int) { return operator--(); }
431  const Iterator &operator+= (int n);
432  const Iterator &operator-= (int n);
433  Iterator operator+ (int n) const;
434  Iterator operator- (int n) const;
435  int operator- (const Iterator &other) const;
436 
442  QVariant key () const;
443  QVariant value () const;
444 
445  inline QVariant operator* () const
446  { return value (); }
447 
448  private:
449  friend class Nuria::Variant;
450  Iterator (const QVariant &variant, void *iter, void *info, int pos);
451  VariantIteratorPrivate *d_ptr;
452 
453  };
454 
460  static Iterator begin (QVariant &variant);
461 
465  static Iterator end (QVariant &variant);
466 
479  static Iterator find (QVariant &variant, QVariant ident);
480 
487  static int itemCount (const QVariant &variant);
488 
493  static bool isList (const QVariant &variant);
494 
496  static bool isList (int typeId);
497 
501  static bool isMap (const QVariant &variant);
502 
504  static bool isMap (int typeId);
505 
510  static bool isGeneric (const QVariant &variant);
511 
513  static bool isGeneric (int typeId);
514 
523  static QVariantList toList (QVariant variant);
524 
534  static QVariantMap toMap (QVariant variant);
535 
546  template< typename ... Items >
547  static QVariantList buildList (const Items &... items) {
548  QVariantList list;
549  buildListImpl (list, items ...);
550  return list;
551  }
552 
561  static void *stealPointer (QVariant &variant);
562 
563 private:
564 
571  // We use C-style casts here so this code doesn't get more unreadable...
572  template< typename T > inline static void iteratorDtor (void *t)
573  { delete (typename T::const_iterator *)t; }
574 
575  template< typename T > inline static void *iteratorCopy (void *t)
576  { return (void *)(new typename T::const_iterator (*(typename T::const_iterator *)t)); }
577 
578  template< typename T > inline static void *iteratorBegin (void *t)
579  { return (void *)(new typename T::const_iterator (((T *)t)->constBegin ())); }
580 
581  template< typename T > inline static void *iteratorEnd (void *t)
582  { return (void *)(new typename T::const_iterator (((T *)t)->constEnd ())); }
583 
584  template< typename T > inline static void iteratorMove (void *t, int n)
585  { (*static_cast< typename T::const_iterator * > (t)) += n; }
586 
587  template< typename T > inline static int iteratorDistance (void *t, void *o) {
588  typename T::const_iterator *l = static_cast< typename T::const_iterator * > (t);
589  typename T::const_iterator *r = static_cast< typename T::const_iterator * > (o);
590  return std::distance (*l, *r);
591  }
592 
593  template< typename T > inline static void iteratorNext (void *t)
594  { ++(*static_cast< typename T::const_iterator * > (t)); }
595 
596  template< typename T > inline static void iteratorPrev (void *t)
597  { --(*static_cast< typename T::const_iterator * > (t)); }
598 
599  template< typename T > inline static QVariant iteratorKey (void *t, int type)
600  { return QVariant::fromValue (static_cast< typename T::const_iterator * > (t)->key ()); }
601 
602  template< typename T > inline static QVariant iteratorValue (void *t, int) {
603  return QVariant::fromValue (*(*static_cast< typename T::const_iterator * > (t)));
604  }
605 
606  template< typename T > inline static bool iteratorEqual (void *t, void *r) {
607  typename T::const_iterator &left = *static_cast< typename T::const_iterator * > (t);
608  typename T::const_iterator &right = *static_cast< typename T::const_iterator * > (r);
609  return (left == right);
610  }
611 
612  template< typename T > inline static int iteratorCount (void *t)
613  { return static_cast< T * > (t)->count (); }
614 
615  template< typename T, typename Key > inline static void *iteratorFindMap (void *t, const QVariant &what) {
616  typename T::const_iterator it = static_cast< T * > (t)
617  ->find (*static_cast< const Key * >(what.constData ()));
618  if (it == static_cast< T * > (t)->end ())
619  return 0;
620  return (void *)(new typename T::const_iterator (it));
621  }
622 
623  template< typename T, typename Key > inline static void *iteratorFindList (void *t, const QVariant &what) {
624  T *list = static_cast< T * > (t);
625  const Key *item = static_cast< const Key * > (qMetaTypeId< Key > () == QMetaType::QVariant
626  ? &what : what.constData ());
627 
628  typename T::const_iterator it = list->begin ();
629  typename T::const_iterator end = list->end ();
630 
631  if (qMetaTypeId< Key > () != QMetaType::QVariant) {
632  for (; it != end; ++it) {
633 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
634  if (equal (*it, what))
635 #else
636  if ((*it).operator== (*item))
637 #endif
638  return new typename T::const_iterator (it);
639  }
640  } else {
641  for (; it != end; ++it) {
642  if (equal (*it, *item))
643  return new typename T::const_iterator (it);
644  }
645  }
646 
647  return 0;
648  }
649 
653  template< typename From, typename To >
654  static To *autoConvTempl (From *from)
655  { return new To (*from); }
656 
660  static void registerIterator (int type, int valueType, int keyType,
661  IteratorDtorFunc dtor, IteratorCopyFunc copy,
662  IteratorStartEndFunc start, IteratorStartEndFunc end,
663  IteratorIncFunc increment, IteratorIncFunc decrement,
664  IteratorMoveFunc move, IteratorDistanceFunc distance,
665  IteratorValueFunc value, IteratorValueFunc key,
666  IteratorComparisonFunc equal,
667  IteratorCountFunc count, IteratorFindFunc find);
668 
670  template< typename T > static inline const T &passThrough (const T &t) { return t; }
671 
672  // Simplifies usage for buildList.
673 #ifndef NURIA_NO_CHAR_ARRAY_TO_QSTRING
674  static inline QString passThrough (const char *str) { return QString (str); }
675 #endif
676 
678  static inline void buildListImpl (QVariantList &) { }
679 
680  //
681  template< typename T, typename ... Items >
682  static inline void buildListImpl (QVariantList &list, const T &cur, const Items & ... items) {
683  list.append (QVariant::fromValue (passThrough (cur)));
684  buildListImpl (list, items ...);
685  }
686 
688  Variant ();
689 
690 };
691 
692 }
693 
694 #ifdef NURIA_VARIANT_COMPARISON
695 inline bool operator== (const QVariant &left, const QVariant &right)
696 { return Nuria::Variant::equal (left, right); }
697 
698 inline bool operator!= (const QVariant &left, const QVariant &right)
699 { return Nuria::Variant::notEqual (left, right); }
700 
701 inline bool operator< (const QVariant &left, const QVariant &right)
702 { return Nuria::Variant::lessThan (left, right); }
703 
704 inline bool operator> (const QVariant &left, const QVariant &right)
705 { return Nuria::Variant::greaterThan (left, right); }
706 
707 inline bool operator<= (const QVariant &left, const QVariant &right)
708 { return Nuria::Variant::lessEqualThan (left, right); }
709 
710 inline bool operator>= (const QVariant &left, const QVariant &right)
711 { return Nuria::Variant::greaterEqualThan (left, right); }
712 #endif
713 
717 #define VARIANT_FOREACH(variable, variant) \
718  for (Nuria::Variant::Iterator _niter_ = Nuria::Variant::begin (variant), \
719  _nend_ = Nuria::Variant::end (variant); \
720  _niter_ != _nend_; ++_niter_) \
721  if (!(variable = _niter_.value()).isNull ())
722 
723 #endif // NURIA_VARIANT_HPP
static void registerType()
Definition: variant.hpp:287
static bool isMap(const QVariant &variant)
static bool canCompare(const QVariant &left, int rightType)
Definition: variant.hpp:184
The Variant class provides utilities for working with QVariants. Working with QVariants can be tediou...
Definition: variant.hpp:112
static void * stealPointer(QVariant &variant)
static void registerIterators(typename T::mapped_type *a=(typename T::mapped_type *) 0)
Definition: variant.hpp:352
static Iterator begin(QVariant &variant)
static QVariantList buildList(const Items &...items)
Definition: variant.hpp:547
static bool canCompare(const QVariant &left, const QVariant &right)
Definition: variant.hpp:178
static bool canCompare(const QVariant &left)
Definition: variant.hpp:190
static Iterator find(QVariant &variant, QVariant ident)
static QVariantList toList(QVariant variant)
static bool canConvert(const QVariant &variant)
Definition: variant.hpp:236
static bool canConvert(const QVariant &variant, int toType)
Definition: variant.hpp:243
static void registerConversion()
Definition: variant.hpp:335
static void registerIterators(typename T::value_type *a=(typename T::value_type *) 0)
Definition: variant.hpp:379
static bool isGeneric(const QVariant &variant)
static void registerType()
Definition: variant.hpp:279
static T toValue(const QVariant &variant)
Definition: variant.hpp:257
static QVariant convert(const QVariant &variant)
Definition: variant.hpp:220
static int itemCount(const QVariant &variant)
static Iterator end(QVariant &variant)
static bool isList(const QVariant &variant)
static void registerConversion(To *(*func)(const From &))
Definition: variant.hpp:321
Definition: variant.hpp:407
static bool canCompare()
Definition: variant.hpp:196
static QVariantMap toMap(QVariant variant)