MetaType: Fix operator{+,-}(int) with the type-erased const_iterators.
Make sure we don't modify the lhs. Instead copy it and advance the copy. Change-Id: I3440e8e175bfc299f8f83b816faca54fa3f79e43 Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
a9770c4b6c
commit
8b0624182b
@ -892,6 +892,7 @@ public:
|
|||||||
typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
|
typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
|
||||||
typedef void (*destroyIterFunc)(void **p);
|
typedef void (*destroyIterFunc)(void **p);
|
||||||
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
|
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
|
||||||
|
typedef void (*copyIterFunc)(void **, void * const *);
|
||||||
|
|
||||||
sizeFunc _size;
|
sizeFunc _size;
|
||||||
atFunc _at;
|
atFunc _at;
|
||||||
@ -901,6 +902,7 @@ public:
|
|||||||
getFunc _get;
|
getFunc _get;
|
||||||
destroyIterFunc _destroyIter;
|
destroyIterFunc _destroyIter;
|
||||||
equalIterFunc _equalIter;
|
equalIterFunc _equalIter;
|
||||||
|
copyIterFunc _copyIter;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static int sizeImpl(const void *p)
|
static int sizeImpl(const void *p)
|
||||||
@ -938,6 +940,10 @@ public:
|
|||||||
static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
|
static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
|
||||||
{ return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
|
{ return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static void copyIterImpl(void **dest, void * const * src)
|
||||||
|
{ IteratorOwner<typename T::const_iterator>::assign(dest, *static_cast<typename T::const_iterator*>(*src)); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class T> QSequentialIterableImpl(const T*p)
|
template<class T> QSequentialIterableImpl(const T*p)
|
||||||
: _iterable(p)
|
: _iterable(p)
|
||||||
@ -953,6 +959,7 @@ public:
|
|||||||
, _get(getImpl<T>)
|
, _get(getImpl<T>)
|
||||||
, _destroyIter(destroyIterImpl<T>)
|
, _destroyIter(destroyIterImpl<T>)
|
||||||
, _equalIter(equalIterImpl<T>)
|
, _equalIter(equalIterImpl<T>)
|
||||||
|
, _copyIter(copyIterImpl<T>)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,6 +977,7 @@ public:
|
|||||||
, _get(0)
|
, _get(0)
|
||||||
, _destroyIter(0)
|
, _destroyIter(0)
|
||||||
, _equalIter(0)
|
, _equalIter(0)
|
||||||
|
, _copyIter(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -990,6 +998,12 @@ public:
|
|||||||
int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
|
int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
|
||||||
|
|
||||||
inline void destroyIter() { _destroyIter(&_iterator); }
|
inline void destroyIter() { _destroyIter(&_iterator); }
|
||||||
|
|
||||||
|
void copy(const QSequentialIterableImpl &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
_copyIter(&_iterator, &other._iterator);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename From>
|
template<typename From>
|
||||||
@ -1055,6 +1069,7 @@ public:
|
|||||||
typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
|
typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
|
||||||
typedef void (*destroyIterFunc)(void **p);
|
typedef void (*destroyIterFunc)(void **p);
|
||||||
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
|
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
|
||||||
|
typedef void (*copyIterFunc)(void **, void * const *);
|
||||||
|
|
||||||
sizeFunc _size;
|
sizeFunc _size;
|
||||||
findFunc _find;
|
findFunc _find;
|
||||||
@ -1065,6 +1080,7 @@ public:
|
|||||||
getFunc _getValue;
|
getFunc _getValue;
|
||||||
destroyIterFunc _destroyIter;
|
destroyIterFunc _destroyIter;
|
||||||
equalIterFunc _equalIter;
|
equalIterFunc _equalIter;
|
||||||
|
copyIterFunc _copyIter;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static int sizeImpl(const void *p)
|
static int sizeImpl(const void *p)
|
||||||
@ -1104,6 +1120,10 @@ public:
|
|||||||
static bool equalIterImpl(void * const *iterator, void * const *other)
|
static bool equalIterImpl(void * const *iterator, void * const *other)
|
||||||
{ return *static_cast<typename T::const_iterator*>(*iterator) == *static_cast<typename T::const_iterator*>(*other); }
|
{ return *static_cast<typename T::const_iterator*>(*iterator) == *static_cast<typename T::const_iterator*>(*other); }
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static void copyIterImpl(void **dest, void * const * src)
|
||||||
|
{ IteratorOwner<typename T::const_iterator>::assign(dest, *static_cast<typename T::const_iterator*>(*src)); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class T> QAssociativeIterableImpl(const T*p)
|
template<class T> QAssociativeIterableImpl(const T*p)
|
||||||
: _iterable(p)
|
: _iterable(p)
|
||||||
@ -1120,6 +1140,7 @@ public:
|
|||||||
, _getValue(getValueImpl<T>)
|
, _getValue(getValueImpl<T>)
|
||||||
, _destroyIter(destroyIterImpl<T>)
|
, _destroyIter(destroyIterImpl<T>)
|
||||||
, _equalIter(equalIterImpl<T>)
|
, _equalIter(equalIterImpl<T>)
|
||||||
|
, _copyIter(copyIterImpl<T>)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,6 +1159,7 @@ public:
|
|||||||
, _getValue(0)
|
, _getValue(0)
|
||||||
, _destroyIter(0)
|
, _destroyIter(0)
|
||||||
, _equalIter(0)
|
, _equalIter(0)
|
||||||
|
, _copyIter(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1155,6 +1177,12 @@ public:
|
|||||||
{ _find(_iterable, key.data, &_iterator); }
|
{ _find(_iterable, key.data, &_iterator); }
|
||||||
|
|
||||||
int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
|
int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
|
||||||
|
|
||||||
|
void copy(const QAssociativeIterableImpl &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
_copyIter(&_iterator, &other._iterator);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename From>
|
template<typename From>
|
||||||
|
@ -615,8 +615,8 @@ public:
|
|||||||
inline const_iterator operator--(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
|
inline const_iterator operator--(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
|
||||||
inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
|
inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
|
||||||
inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
|
inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
|
||||||
inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); }
|
inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl; impl.copy(m_impl); impl.advance(j); return const_iterator(impl, new QAtomicInt(0)); }
|
||||||
inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); }
|
inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl; impl.copy(m_impl); impl.advance(-j); return const_iterator(impl, new QAtomicInt(0)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct const_iterator;
|
friend struct const_iterator;
|
||||||
@ -700,8 +700,8 @@ public:
|
|||||||
inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
|
inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); }
|
||||||
inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
|
inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; }
|
||||||
inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
|
inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; }
|
||||||
inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); }
|
inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl; impl.copy(m_impl); impl.advance(j); return const_iterator(impl, new QAtomicInt(0)); }
|
||||||
inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); }
|
inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl; impl.copy(m_impl); impl.advance(-j); return const_iterator(impl, new QAtomicInt(0)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct const_iterator;
|
friend struct const_iterator;
|
||||||
|
@ -3818,6 +3818,20 @@ void tst_QVariant::iterateContainerElements()
|
|||||||
TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
|
TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
QVariantList ints;
|
||||||
|
ints << 1 << 2 << 3;
|
||||||
|
QVariant var = QVariant::fromValue(ints);
|
||||||
|
QSequentialIterable iter = var.value<QSequentialIterable>();
|
||||||
|
QSequentialIterable::const_iterator it = iter.begin();
|
||||||
|
QSequentialIterable::const_iterator end = iter.end();
|
||||||
|
QCOMPARE(ints.at(1), *(it + 1));
|
||||||
|
int i = 0;
|
||||||
|
for ( ; it != end; ++it, ++i) {
|
||||||
|
QCOMPARE(ints.at(i), *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define TEST_ASSOCIATIVE_ITERATION(CONTAINER, KEY_TYPE, MAPPED_TYPE) \
|
#define TEST_ASSOCIATIVE_ITERATION(CONTAINER, KEY_TYPE, MAPPED_TYPE) \
|
||||||
{ \
|
{ \
|
||||||
int numSeen = 0; \
|
int numSeen = 0; \
|
||||||
@ -3852,6 +3866,22 @@ void tst_QVariant::iterateContainerElements()
|
|||||||
#ifdef TEST_UNORDERED_MAP
|
#ifdef TEST_UNORDERED_MAP
|
||||||
TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool)
|
TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
QMap<int, QString> mapping;
|
||||||
|
mapping.insert(1, "one");
|
||||||
|
mapping.insert(2, "two");
|
||||||
|
mapping.insert(3, "three");
|
||||||
|
QVariant var = QVariant::fromValue(mapping);
|
||||||
|
QAssociativeIterable iter = var.value<QAssociativeIterable>();
|
||||||
|
QAssociativeIterable::const_iterator it = iter.begin();
|
||||||
|
QAssociativeIterable::const_iterator end = iter.end();
|
||||||
|
QCOMPARE(*(mapping.begin() + 1), (*(it + 1)).toString());
|
||||||
|
int i = 0;
|
||||||
|
for ( ; it != end; ++it, ++i) {
|
||||||
|
QCOMPARE(*(mapping.begin() + i), (*it).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QVariant::pairElements()
|
void tst_QVariant::pairElements()
|
||||||
|
Loading…
Reference in New Issue
Block a user