123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 | // Copyright (C) 2020 The Qt Company Ltd.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#ifndef QITERABLE_H#define QITERABLE_H#include <QtCore/qglobal.h>#include <QtCore/qtypeinfo.h>#include <QtCore/qmetacontainer.h>#include <QtCore/qtaggedpointer.h> QT_BEGIN_NAMESPACE namespace QtPrivate {template<typename Type, typename Storage = Type>class QConstPreservingPointer {enum Tag :bool{ Const, Mutable }; QTaggedPointer<Storage, Tag> m_pointer;public: Q_NODISCARD_CTOR QConstPreservingPointer(std::nullptr_t) :m_pointer(nullptr, Const) {} Q_NODISCARD_CTOR QConstPreservingPointer(const void*pointer, qsizetype alignment):m_pointer(reinterpret_cast<Storage *>(const_cast<void*>(pointer)), Const){Q_UNUSED(alignment);Q_ASSERT(alignment >qsizetype(alignof(Storage)));} Q_NODISCARD_CTOR QConstPreservingPointer(void*pointer, qsizetype alignment):m_pointer(reinterpret_cast<Storage *>(pointer), Mutable){Q_UNUSED(alignment);Q_ASSERT(alignment >qsizetype(alignof(Storage)));}template<typename InputType> Q_NODISCARD_CTOR QConstPreservingPointer(const InputType *pointer):m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const){static_assert(alignof(InputType) >=alignof(Storage));}template<typename InputType> Q_NODISCARD_CTOR QConstPreservingPointer(InputType *pointer):m_pointer(reinterpret_cast<Storage *>(pointer), Mutable){static_assert(alignof(InputType) >=alignof(Storage));} Q_NODISCARD_CTOR QConstPreservingPointer() =default;const Type *constPointer()const{return reinterpret_cast<const Type *>(m_pointer.data());} Type *mutablePointer()const{return m_pointer.tag() == Mutable ?reinterpret_cast<Type *>(m_pointer.data()) :nullptr;}};}template<class Iterator, typename IteratorCategory>class QTaggedIterator :public Iterator {public:using iterator_category = IteratorCategory;QTaggedIterator(Iterator &&it) :Iterator(std::move(it)){const QMetaContainer metaContainer =this->metaContainer();ifconstexpr(std::is_base_of_v<std::random_access_iterator_tag, IteratorCategory>) {if(!metaContainer.hasRandomAccessIterator()) {qFatal("You cannot use this iterator as a random access iterator");this->clearIterator();}}ifconstexpr(std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategory>) {if(!metaContainer.hasBidirectionalIterator()) {qFatal("You cannot use this iterator as a bidirectional iterator");this->clearIterator();}}ifconstexpr(std::is_base_of_v<std::forward_iterator_tag, IteratorCategory>) {if(!metaContainer.hasForwardIterator()) {qFatal("You cannot use this iterator as a forward iterator");this->clearIterator();}}ifconstexpr(std::is_base_of_v<std::input_iterator_tag, IteratorCategory>) {if(!metaContainer.hasInputIterator()) {qFatal("You cannot use this iterator as an input iterator");this->clearIterator();}}}booloperator==(const QTaggedIterator &o)const{returnIterator::operator==(o); }booloperator!=(const QTaggedIterator &o)const{returnIterator::operator!=(o); } QTaggedIterator &operator++() {Iterator::operator++();return*this; } QTaggedIterator operator++(int x) {returnQTaggedIterator(Iterator::operator++(x)); } QTaggedIterator &operator--() {Iterator::operator--();return*this; } QTaggedIterator operator--(int x) {returnQTaggedIterator(Iterator::operator--(x)); } QTaggedIterator &operator+=(qsizetype j) {Iterator::operator+=(j);return*this; } QTaggedIterator &operator-=(qsizetype j) {Iterator::operator-=(j);return*this; } QTaggedIterator operator+(qsizetype j)const{returnQTaggedIterator(Iterator::operator+(j)); } QTaggedIterator operator-(qsizetype j)const{returnQTaggedIterator(Iterator::operator-(j)); } qsizetype operator-(const QTaggedIterator &j)const{returnIterator::operator-(j); }booloperator<(const QTaggedIterator &j) {returnoperator-(j) <0; }booloperator>=(const QTaggedIterator &j) {return!operator<(j); }booloperator>(const QTaggedIterator &j) {returnoperator-(j) >0; }booloperator<=(const QTaggedIterator &j) {return!operator>(j); }friend inline QTaggedIterator operator+(qsizetype j,const QTaggedIterator &k) {return k + j; }};template<class Container>class QIterable;template<class Container>class QBaseIterator {private:QtPrivate::QConstPreservingPointer<QIterable<Container>> m_iterable;void*m_iterator =nullptr;protected:QBaseIterator() =default;QBaseIterator(const QIterable<Container> *iterable,void*iterator):m_iterable(iterable),m_iterator(iterator){}QBaseIterator(QIterable<Container> *iterable,void*iterator):m_iterable(iterable),m_iterator(iterator){}QBaseIterator(QBaseIterator &&other):m_iterable(std::move(other.m_iterable)),m_iterator(std::move(other.m_iterator)){ other.m_iterator =nullptr;}QBaseIterator(const QBaseIterator &other):m_iterable(other.m_iterable){initIterator(other.m_iterator);}~QBaseIterator() {clearIterator(); } QBaseIterator &operator=(QBaseIterator &&other){if(this!= &other) {clearIterator(); m_iterable =std::move(other.m_iterable); m_iterator =std::move(other.m_iterator); other.m_iterator =nullptr;}return*this;} QBaseIterator &operator=(const QBaseIterator &other){if(this!= &other) {clearIterator(); m_iterable = other.m_iterable;initIterator(other.m_iterator);}return*this;} QIterable<Container> *mutableIterable()const{return m_iterable.mutablePointer();}const QIterable<Container> *constIterable()const{return m_iterable.constPointer();}voidinitIterator(const void*copy){if(!copy)return;if(auto*mutableIt =mutableIterable()) { m_iterator =metaContainer().begin(mutableIt->mutableIterable());metaContainer().copyIterator(m_iterator, copy);}else if(auto*constIt =constIterable()) { m_iterator =metaContainer().constBegin(constIt->constIterable());metaContainer().copyConstIterator(m_iterator, copy);}}voidclearIterator(){if(!m_iterator)return;if(mutableIterable())metaContainer().destroyIterator(m_iterator);elsemetaContainer().destroyConstIterator(m_iterator);}public:void*mutableIterator() {return m_iterator; }const void*constIterator()const{return m_iterator; } Container metaContainer()const{returnconstIterable()->m_metaContainer; }};template<class Container>struct QIterator :public QBaseIterator<Container>{public:using difference_type = qsizetype;explicitQIterator(QIterable<Container> *iterable,void*iterator): QBaseIterator<Container>(iterable, iterator){Q_ASSERT(iterable !=nullptr);}booloperator==(const QIterator &o)const{return this->metaContainer().compareIterator(this->constIterator(), o.constIterator());}booloperator!=(const QIterator &o)const{return!this->metaContainer().compareIterator(this->constIterator(), o.constIterator());} QIterator &operator++(){this->metaContainer().advanceIterator(this->mutableIterator(),1);return*this;} QIterator operator++(int){ QIterable<Container> *iterable =this->mutableIterable();const Container metaContainer =this->metaContainer(); QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); metaContainer.copyIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceIterator(this->mutableIterator(),1);return result;} QIterator &operator--(){this->metaContainer().advanceIterator(this->mutableIterator(), -1);return*this;} QIterator operator--(int){ QIterable<Container> *iterable =this->mutableIterable();const Container metaContainer =this->metaContainer(); QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); metaContainer.copyIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceIterator(this->mutableIterator(), -1);return result;} QIterator &operator+=(qsizetype j){this->metaContainer().advanceIterator(this->mutableIterator(), j);return*this;} QIterator &operator-=(qsizetype j){this->metaContainer().advanceIterator(this->mutableIterator(), -j);return*this;} QIterator operator+(qsizetype j)const{ QIterable<Container> *iterable =this->mutableIterable();const Container metaContainer =this->metaContainer(); QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); metaContainer.copyIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceIterator(result.mutableIterator(), j);return result;} QIterator operator-(qsizetype j)const{ QIterable<Container> *iterable =this->mutableIterable();const Container metaContainer =this->metaContainer(); QIterator result(iterable, metaContainer.begin(iterable->mutableIterable())); metaContainer.copyIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceIterator(result.mutableIterator(), -j);return result;} qsizetype operator-(const QIterator &j)const{return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());}friend inline QIterator operator+(qsizetype j,const QIterator &k) {return k + j; }};template<class Container>struct QConstIterator :public QBaseIterator<Container>{public:using difference_type = qsizetype;explicitQConstIterator(const QIterable<Container> *iterable,void*iterator): QBaseIterator<Container>(iterable, iterator){}booloperator==(const QConstIterator &o)const{return this->metaContainer().compareConstIterator(this->constIterator(), o.constIterator());}booloperator!=(const QConstIterator &o)const{return!this->metaContainer().compareConstIterator(this->constIterator(), o.constIterator());} QConstIterator &operator++(){this->metaContainer().advanceConstIterator(this->mutableIterator(),1);return*this;} QConstIterator operator++(int){const Container metaContainer =this->metaContainer(); QConstIterator result(this->constIterable(), metaContainer.constBegin(this->constIterable()->constIterable())); metaContainer.copyConstIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceConstIterator(this->mutableIterator(),1);return result;} QConstIterator &operator--(){this->metaContainer().advanceConstIterator(this->mutableIterator(), -1);return*this;} QConstIterator operator--(int){const Container metaContainer =this->metaContainer(); QConstIterator result(this->constIterable(), metaContainer.constBegin(this->constIterable()->constIterable())); metaContainer.copyConstIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceConstIterator(this->mutableIterator(), -1);return result;} QConstIterator &operator+=(qsizetype j){this->metaContainer().advanceConstIterator(this->mutableIterator(), j);return*this;} QConstIterator &operator-=(qsizetype j){this->metaContainer().advanceConstIterator(this->mutableIterator(), -j);return*this;} QConstIterator operator+(qsizetype j)const{const Container metaContainer =this->metaContainer(); QConstIterator result(this->constIterable(), metaContainer.constBegin(this->constIterable()->constIterable())); metaContainer.copyConstIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceConstIterator(result.mutableIterator(), j);return result;} QConstIterator operator-(qsizetype j)const{const Container metaContainer =this->metaContainer(); QConstIterator result(this->constIterable(), metaContainer.constBegin(this->constIterable()->constIterable())); metaContainer.copyConstIterator(result.mutableIterator(),this->constIterator()); metaContainer.advanceConstIterator(result.mutableIterator(), -j);return result;} qsizetype operator-(const QConstIterator &j)const{return this->metaContainer().diffIterator(this->constIterator(), j.constIterator());}friend inline QConstIterator operator+(qsizetype j,const QConstIterator &k){return k + j;}};template<class Container>class QIterable {friend class QBaseIterator<Container>;protected: uint m_revision =0;QtPrivate::QConstPreservingPointer<void, quint16> m_iterable; Container m_metaContainer;public:template<class T>QIterable(const Container &metaContainer,const T *p):m_iterable(p),m_metaContainer(metaContainer){}template<class T>QIterable(const Container &metaContainer, T *p):m_iterable(p),m_metaContainer(metaContainer){}template<typename Pointer>QIterable(const Container &metaContainer, Pointer iterable):m_iterable(iterable),m_metaContainer(metaContainer){}QIterable(const Container &metaContainer, qsizetype alignment,const void*p):m_iterable(p, alignment),m_metaContainer(metaContainer){}QIterable(const Container &metaContainer, qsizetype alignment,void*p):m_iterable(p, alignment),m_metaContainer(metaContainer){}boolcanInputIterate()const{return m_metaContainer.hasInputIterator();}boolcanForwardIterate()const{return m_metaContainer.hasForwardIterator();}boolcanReverseIterate()const{return m_metaContainer.hasBidirectionalIterator();}boolcanRandomAccessIterate()const{return m_metaContainer.hasRandomAccessIterator();}const void*constIterable()const{return m_iterable.constPointer(); }void*mutableIterable() {return m_iterable.mutablePointer(); } QConstIterator<Container>constBegin()const{returnQConstIterator(this, m_metaContainer.constBegin(constIterable()));} QConstIterator<Container>constEnd()const{returnQConstIterator(this, m_metaContainer.constEnd(constIterable()));} QIterator<Container>mutableBegin(){returnQIterator(this, m_metaContainer.begin(mutableIterable()));} QIterator<Container>mutableEnd(){returnQIterator(this, m_metaContainer.end(mutableIterable()));} qsizetype size()const{const void*container =constIterable();if(m_metaContainer.hasSize())return m_metaContainer.size(container);if(!m_metaContainer.hasConstIterator())return-1;const void*begin = m_metaContainer.constBegin(container);const void*end = m_metaContainer.constEnd(container);const qsizetype size = m_metaContainer.diffConstIterator(end, begin); m_metaContainer.destroyConstIterator(begin); m_metaContainer.destroyConstIterator(end);return size;} Container metaContainer()const{return m_metaContainer;}}; QT_END_NAMESPACE #endif// QITERABLE_H
|