From a4fb128b733667dcc8269efbb1b0227f09e3a64c Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 2 Jan 2020 13:27:10 +0100 Subject: QSequentialIterableImpl: support append Task-number: QTBUG-80916 Change-Id: I87e74da0ce454e56b5fe94d9db3693a587d35edf Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Shawn Rutledge Reviewed-by: Ulf Hermann --- src/corelib/kernel/qmetatype.h | 88 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index d41f7ee80e..d13fdeb642 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -977,6 +977,30 @@ enum IteratorCapability RandomAccessCapability = 4 }; +enum ContainerCapability +{ + ContainerIsAppendable = 1 +}; + +template +struct ContainerCapabilitiesImpl +{ + enum {ContainerCapabilities = 0}; + using appendFunction = void(*)(const void *container, const void *newElement); + static constexpr const appendFunction appendImpl = nullptr; +}; + +template +struct ContainerCapabilitiesImpl().push_back(std::declval()))> +{ + 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(const_cast(container))->push_back(*static_cast(value)); } +}; + template::iterator_category> struct CapabilitiesImpl; @@ -1012,6 +1036,12 @@ template struct ContainerAPI > : CapabilitiesImpl > { static int size(const std::list *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: @@ -1020,19 +1050,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(_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; @@ -1059,6 +1107,15 @@ public: static void moveToEndImpl(const void *container, void **iterator) { IteratorOwner::assign(iterator, static_cast(container)->end()); } + template + static void moveToImpl(const void *container, void **iterator, Position position) + { + if (position == ToBegin) + moveToBeginImpl(container, iterator); + else + moveToEndImpl(container, iterator); + } + template static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags) { return VariantData(metaTypeId, IteratorOwner::getData(iterator), flags); } @@ -1069,11 +1126,11 @@ public: , _iterator(nullptr) , _metaType_id(qMetaTypeId()) , _metaType_flags(QTypeInfo::isPointer) - , _iteratorCapabilities(ContainerAPI::IteratorCapabilities) + , _iteratorCapabilities(ContainerAPI::IteratorCapabilities | (1 << 4) | (ContainerCapabilitiesImpl::ContainerCapabilities << (4+3))) , _size(sizeImpl) , _at(atImpl) - , _moveToBegin(moveToBeginImpl) - , _moveToEnd(moveToEndImpl) + , _moveTo(moveToImpl) + , _append(ContainerCapabilitiesImpl::appendImpl) , _advance(IteratorOwner::advance) , _get(getImpl) , _destroyIter(IteratorOwner::destroy) @@ -1087,7 +1144,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) @@ -1100,8 +1157,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); @@ -1109,6 +1176,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 -- cgit v1.2.3