diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-01-29 01:00:55 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-01-29 01:00:56 +0100 |
commit | a3fc03c13032b779f74ef496977d2e19e415227a (patch) | |
tree | ff4c8457111c1c9631a2f7adc4938f151ac650b2 /src/corelib/kernel/qmetatype.h | |
parent | 94bc57213f9a8a74e9e7520de68d7bba7f42ea4c (diff) | |
parent | 382619de6592ff9583504bd31176bf8dc51b0771 (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I98b1a5a11ece3957a1115c1d9be8841759206ffe
Diffstat (limited to 'src/corelib/kernel/qmetatype.h')
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 4f70eb4c6d..59ec8de0e9 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -990,6 +990,30 @@ enum IteratorCapability RandomAccessCapability = 4 }; +enum ContainerCapability +{ + ContainerIsAppendable = 1 +}; + +template<typename Container, typename T = void> +struct ContainerCapabilitiesImpl +{ + enum {ContainerCapabilities = 0}; + using appendFunction = void(*)(const void *container, const void *newElement); + static constexpr const appendFunction appendImpl = nullptr; +}; + +template<typename Container> +struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()))> +{ + enum {ContainerCapabilities = ContainerIsAppendable}; + + // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl + // pointed to a const object to begin with + static void appendImpl(const void *container, const void *value) + { static_cast<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); } +}; + template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category> struct CapabilitiesImpl; @@ -1025,6 +1049,12 @@ template<typename T> struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> > { static int size(const std::list<T> *t) { return int(t->size()); } }; +/* + revision 0: _iteratorCapabilities is simply a uint, where the bits at _revision were never set + revision 1: _iteratorCapabilties is treated as a bitfield, the remaining bits are used to introduce + _revision, _containerCapabilities and _unused. The latter contains 21 bits that are + not used yet +*/ class QSequentialIterableImpl { public: @@ -1033,19 +1063,37 @@ public: int _metaType_id; uint _metaType_flags; uint _iteratorCapabilities; + // Iterator capabilities looks actually like + // uint _iteratorCapabilities:4; + // uint _revision:3; + // uint _containerCapabilities:4; + // uint _unused:21;*/ typedef int(*sizeFunc)(const void *p); typedef const void * (*atFunc)(const void *p, int); typedef void (*moveIteratorFunc)(const void *p, void **); + enum Position { ToBegin, ToEnd }; + typedef void (*moveIteratorFunc2)(const void *p, void **, Position position); typedef void (*advanceFunc)(void **p, int); typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags); typedef void (*destroyIterFunc)(void **p); typedef bool (*equalIterFunc)(void * const *p, void * const *other); typedef void (*copyIterFunc)(void **, void * const *); + typedef void(*appendFunction)(const void *container, const void *newElement); + + IteratorCapability iteratorCapabilities() {return static_cast<IteratorCapability>(_iteratorCapabilities & 0xF);} + uint revision() {return _iteratorCapabilities >> 4 & 0x7;} + uint containerCapabilities() {return _iteratorCapabilities >> 7 & 0xF;} sizeFunc _size; atFunc _at; - moveIteratorFunc _moveToBegin; - moveIteratorFunc _moveToEnd; + union { + moveIteratorFunc _moveToBegin; + moveIteratorFunc2 _moveTo; + }; + union { + moveIteratorFunc _moveToEnd; + appendFunction _append; + }; advanceFunc _advance; getFunc _get; destroyIterFunc _destroyIter; @@ -1072,6 +1120,15 @@ public: static void moveToEndImpl(const void *container, void **iterator) { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); } + template<class Container> + static void moveToImpl(const void *container, void **iterator, Position position) + { + if (position == ToBegin) + moveToBeginImpl<Container>(container, iterator); + else + moveToEndImpl<Container>(container, iterator); + } + template<class T> static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags) { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); } @@ -1082,11 +1139,11 @@ public: , _iterator(nullptr) , _metaType_id(qMetaTypeId<typename T::value_type>()) , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer) - , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities) + , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities | (1 << 4) | (ContainerCapabilitiesImpl<T>::ContainerCapabilities << (4+3))) , _size(sizeImpl<T>) , _at(atImpl<T>) - , _moveToBegin(moveToBeginImpl<T>) - , _moveToEnd(moveToEndImpl<T>) + , _moveTo(moveToImpl<T>) + , _append(ContainerCapabilitiesImpl<T>::appendImpl) , _advance(IteratorOwner<typename T::const_iterator>::advance) , _get(getImpl<T>) , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy) @@ -1100,7 +1157,7 @@ public: , _iterator(nullptr) , _metaType_id(QMetaType::UnknownType) , _metaType_flags(0) - , _iteratorCapabilities(0) + , _iteratorCapabilities(0 | (1 << 4) ) // no iterator capabilities, revision 1 , _size(nullptr) , _at(nullptr) , _moveToBegin(nullptr) @@ -1113,8 +1170,18 @@ public: { } - inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); } - inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); } + inline void moveToBegin() { + if (revision() == 0) + _moveToBegin(_iterable, &_iterator); + else + _moveTo(_iterable, &_iterator, ToBegin); + } + inline void moveToEnd() { + if (revision() == 0) + _moveToEnd(_iterable, &_iterator); + else + _moveTo(_iterable, &_iterator, ToEnd); + } inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); } inline QSequentialIterableImpl &advance(int i) { Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability); @@ -1122,6 +1189,11 @@ public: return *this; } + inline void append(const void *newElement) { + if (containerCapabilities() & ContainerIsAppendable) + _append(_iterable, newElement); + } + inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); } VariantData at(int idx) const |