Provide methods for adding values to a sequential iterable
Provide functionality to add and remove values, so that you can use a sequential iterable as stack or queue if the underlying container supports this. To this end, provide a way to specify whether the value should be added or removed at the beginning or the end of the iterable. Change-Id: If63d302f3ca085e56d601116ce4dfaa6b94a0c4f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>bb10
parent
73fe229eb4
commit
ef93fdeb09
|
|
@ -133,6 +133,73 @@ qsizetype QSequentialIterable::size() const
|
|||
return size;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Adds \a value to the container, at \a position, if possible.
|
||||
*/
|
||||
void QSequentialIterable::addValue(const QVariant &value, Position position)
|
||||
{
|
||||
QVariant converted;
|
||||
const void *valuePtr;
|
||||
if (valueMetaType() == QMetaType::fromType<QVariant>()) {
|
||||
valuePtr = &value;
|
||||
} else if (valueMetaType() == value.metaType()) {
|
||||
valuePtr = value.constData();
|
||||
} else if (value.canConvert(valueMetaType())) {
|
||||
converted = value;
|
||||
converted.convert(valueMetaType());
|
||||
valuePtr = converted.constData();
|
||||
} else {
|
||||
converted = QVariant(valueMetaType());
|
||||
valuePtr = converted.constData();
|
||||
}
|
||||
|
||||
switch (position) {
|
||||
case AtBegin:
|
||||
if (metaSequence().canAddValueAtBegin())
|
||||
metaSequence().addValueAtBegin(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case AtEnd:
|
||||
if (metaSequence().canAddValueAtEnd())
|
||||
metaSequence().addValueAtEnd(mutableIterable(), valuePtr);
|
||||
break;
|
||||
case Unspecified:
|
||||
if (metaSequence().canAddValue())
|
||||
metaSequence().addValue(mutableIterable(), valuePtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Removes a value from the container, at \a position, if possible.
|
||||
*/
|
||||
void QSequentialIterable::removeValue(Position position)
|
||||
{
|
||||
switch (position) {
|
||||
case AtBegin:
|
||||
if (metaSequence().canRemoveValueAtBegin())
|
||||
metaSequence().removeValueAtBegin(mutableIterable());
|
||||
break;
|
||||
case AtEnd:
|
||||
if (metaSequence().canRemoveValueAtEnd())
|
||||
metaSequence().removeValueAtEnd(mutableIterable());
|
||||
break;
|
||||
case Unspecified:
|
||||
if (metaSequence().canRemoveValue())
|
||||
metaSequence().removeValue(mutableIterable());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether it is possible to iterate over the container in forward
|
||||
direction. This corresponds to the std::forward_iterator_tag iterator trait
|
||||
of the iterator and const_iterator of the container.
|
||||
*/
|
||||
bool QSequentialIterable::canForwardIterate() const
|
||||
{
|
||||
return m_metaSequence.hasForwardIterator();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns whether it is possible to iterate over the container in reverse. This
|
||||
corresponds to the std::bidirectional_iterator_tag iterator trait of the
|
||||
|
|
|
|||
|
|
@ -163,10 +163,20 @@ public:
|
|||
QVariant at(qsizetype idx) const;
|
||||
qsizetype size() const;
|
||||
|
||||
enum Position { Unspecified, AtBegin, AtEnd };
|
||||
void addValue(const QVariant &value, Position position = Unspecified);
|
||||
void removeValue(Position position = Unspecified);
|
||||
|
||||
bool canForwardIterate() const;
|
||||
bool canReverseIterate() const;
|
||||
|
||||
const void *constIterable() const { return m_iterable.constPointer(); }
|
||||
|
||||
// TODO: fix this when introducing mutable iterables
|
||||
void *mutableIterable() { return const_cast<void *>(m_iterable.constPointer()); }
|
||||
|
||||
QMetaSequence metaSequence() const { return m_metaSequence; }
|
||||
QMetaType valueMetaType() const { return m_metaSequence.valueMetaType(); }
|
||||
};
|
||||
|
||||
namespace QtPrivate {
|
||||
|
|
|
|||
|
|
@ -144,51 +144,134 @@ QMetaType QMetaSequence::valueMetaType() const
|
|||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the underlying container is ordered, otherwise returns
|
||||
\c false. A container is considered ordered if values added to it are
|
||||
placed in a defined location. Inserting into or adding to an ordered
|
||||
container will always succeed. Inserting into or adding to an unordered
|
||||
Returns \c true if the underlying container is sortable, otherwise returns
|
||||
\c false. A container is considered sortable if values added to it are
|
||||
placed in a defined location. Inserting into or adding to a sortable
|
||||
container will always succeed. Inserting into or adding to an unsortable
|
||||
container may not succeed, for example if the container is a QSet that
|
||||
already contains the value being inserted.
|
||||
|
||||
\sa addValue(), insertValueAtIterator(), addsAndRemovesValuesAtBegin(),
|
||||
addsAndRemovesValuesAtEnd()
|
||||
\sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
|
||||
canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
|
||||
*/
|
||||
bool QMetaSequence::isOrdered() const
|
||||
bool QMetaSequence::isSortable() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition != QtMetaContainerPrivate::QMetaSequenceInterface::Random;
|
||||
if (d_ptr) {
|
||||
return (d_ptr->addRemoveCapabilities
|
||||
& (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
|
||||
&& (d_ptr->addRemoveCapabilities
|
||||
& (QtMetaContainerPrivate::CanRemoveAtBegin
|
||||
| QtMetaContainerPrivate::CanRemoveAtEnd));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values added using \l addValue() are placed at the
|
||||
beginning of the container, otherwise returns \c false. Likewise
|
||||
\l removeValue() removes an value from the beginning of the container
|
||||
if this method returns \c true.
|
||||
Returns \c true if values added using \l addValue() can be placed at the
|
||||
beginning of the container, otherwise returns \c false.
|
||||
|
||||
\sa addValue(), removeValue(), addsAndRemovesValuesAtEnd()
|
||||
\sa addValueAtBegin(), canAddValueAtEnd()
|
||||
*/
|
||||
bool QMetaSequence::addsAndRemovesValuesAtBegin() const
|
||||
bool QMetaSequence::canAddValueAtBegin() const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin;
|
||||
if (d_ptr) {
|
||||
return d_ptr->addValueFn
|
||||
&& d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values added using \l addValue() are placed at the
|
||||
end of the container, otherwise returns \c false. Likewise
|
||||
\l removeValue() removes an value from the end of the container
|
||||
if this method returns \c true.
|
||||
Adds \a value to the beginning of \a container if possible. If
|
||||
\l canAddValueAtBegin() returns \c false, the \a value is not added.
|
||||
|
||||
\sa addValue(), removeValue(), addsAndRemovesValuesAtBegin()
|
||||
\sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
|
||||
*/
|
||||
bool QMetaSequence::addsAndRemovesValuesAtEnd() const
|
||||
void QMetaSequence::addValueAtBegin(void *container, const void *value) const
|
||||
{
|
||||
if (!d_ptr)
|
||||
return false;
|
||||
return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd;
|
||||
if (canAddValueAtBegin())
|
||||
d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values can be removed from the beginning of the container
|
||||
using \l removeValue() can be placed at the, otherwise returns \c false.
|
||||
|
||||
\sa removeValueAtBegin(), canRemoveValueAtEnd()
|
||||
*/
|
||||
bool QMetaSequence::canRemoveValueAtBegin() const
|
||||
{
|
||||
if (d_ptr) {
|
||||
return d_ptr->removeValueFn
|
||||
&& d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a value from the beginning of \a container if possible. If
|
||||
\l canRemoveValueAtBegin() returns \c false, the \a value is not removeed.
|
||||
|
||||
\sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
|
||||
*/
|
||||
void QMetaSequence::removeValueAtBegin(void *container) const
|
||||
{
|
||||
if (canRemoveValueAtBegin())
|
||||
d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values added using \l addValue() can be placed at the
|
||||
end of the container, otherwise returns \c false.
|
||||
|
||||
\sa addValueAtEnd(), canAddValueAtBegin()
|
||||
*/
|
||||
bool QMetaSequence::canAddValueAtEnd() const
|
||||
{
|
||||
if (d_ptr) {
|
||||
return d_ptr->addValueFn
|
||||
&& d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds \a value to the end of \a container if possible. If
|
||||
\l canAddValueAtEnd() returns \c false, the \a value is not added.
|
||||
|
||||
\sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
|
||||
*/
|
||||
void QMetaSequence::addValueAtEnd(void *container, const void *value) const
|
||||
{
|
||||
if (canAddValueAtEnd())
|
||||
d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values can be removed from the end of the container
|
||||
using \l removeValue() can be placed at the, otherwise returns \c false.
|
||||
|
||||
\sa removeValueAtEnd(), canRemoveValueAtBegin()
|
||||
*/
|
||||
bool QMetaSequence::canRemoveValueAtEnd() const
|
||||
{
|
||||
if (d_ptr) {
|
||||
return d_ptr->removeValueFn
|
||||
&& d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a value from the end of \a container if possible. If
|
||||
\l canRemoveValueAtEnd() returns \c false, the \a value is not removeed.
|
||||
|
||||
\sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
|
||||
*/
|
||||
void QMetaSequence::removeValueAtEnd(void *container) const
|
||||
{
|
||||
if (canRemoveValueAtEnd())
|
||||
d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -284,7 +367,7 @@ void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void
|
|||
Returns \c true if values can be added to the container, \c false
|
||||
otherwise.
|
||||
|
||||
\sa addValue(), isOrdered()
|
||||
\sa addValue(), isSortable()
|
||||
*/
|
||||
bool QMetaSequence::canAddValue() const
|
||||
{
|
||||
|
|
@ -294,27 +377,29 @@ bool QMetaSequence::canAddValue() const
|
|||
/*!
|
||||
Adds \a value to the \a container if possible. If \l canAddValue()
|
||||
returns \c false, the \a value is not added. Else, if
|
||||
\l addsAndRemovesValuesAtBegin() returns \c true, the \a value is added
|
||||
to the beginning of the \a container. Else, if
|
||||
\l addsAndRemovesValuesAtEnd() returns \c true, the \a value is added to
|
||||
the end of the container. Else, the value is added in an unspecified
|
||||
\l canAddValueAtEnd() returns \c true, the \a value is added
|
||||
to the end of the \a container. Else, if
|
||||
\l canAddValueAtBegin() returns \c true, the \a value is added to
|
||||
the beginning of the container. Else, the value is added in an unspecified
|
||||
place or not at all. The latter is the case for adding values to an
|
||||
unordered container, for example \l QSet.
|
||||
|
||||
\sa canAddValue(), addsAndRemovesValuesAtBegin(),
|
||||
addsAndRemovesValuesAtEnd(), isOrdered(), removeValue()
|
||||
\sa canAddValue(), canAddValueAtBegin(),
|
||||
canAddValueAtEnd(), isSortable(), removeValue()
|
||||
*/
|
||||
void QMetaSequence::addValue(void *container, const void *value) const
|
||||
{
|
||||
if (canAddValue())
|
||||
d_ptr->addValueFn(container, value);
|
||||
if (canAddValue()) {
|
||||
d_ptr->addValueFn(container, value,
|
||||
QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if values can be removed from the container, \c false
|
||||
otherwise.
|
||||
|
||||
\sa removeValue(), isOrdered()
|
||||
\sa removeValue(), isSortable()
|
||||
*/
|
||||
bool QMetaSequence::canRemoveValue() const
|
||||
{
|
||||
|
|
@ -324,18 +409,20 @@ bool QMetaSequence::canRemoveValue() const
|
|||
/*!
|
||||
Removes an value from the \a container if possible. If
|
||||
\l canRemoveValue() returns \c false, no value is removed. Else, if
|
||||
\l addsAndRemovesValuesAtBegin() returns \c true, the first value in
|
||||
the \a container is removed. Else, if \l addsAndRemovesValuesAtEnd()
|
||||
returns \c true, the last value in the \a container is removed. Else,
|
||||
\l canRemoveValueAtEnd() returns \c true, the last value in
|
||||
the \a container is removed. Else, if \l canRemoveValueAtBegin()
|
||||
returns \c true, the first value in the \a container is removed. Else,
|
||||
an unspecified value or nothing is removed.
|
||||
|
||||
\sa canRemoveValue(), addsAndRemovesValuesAtBegin(),
|
||||
addsAndRemovesValuesAtEnd(), isOrdered(), addValue()
|
||||
\sa canRemoveValue(), canRemoveValueAtBegin(),
|
||||
canRemoveValueAtEnd(), isSortable(), addValue()
|
||||
*/
|
||||
void QMetaSequence::removeValue(void *container) const
|
||||
{
|
||||
if (canRemoveValue())
|
||||
d_ptr->removeValueFn(container);
|
||||
if (canRemoveValue()) {
|
||||
d_ptr->removeValueFn(container,
|
||||
QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -514,14 +601,14 @@ bool QMetaSequence::canInsertValueAtIterator() const
|
|||
/*!
|
||||
Inserts \a value into the \a container, if possible, taking the non-const
|
||||
\a iterator into account. If \l canInsertValueAtIterator() returns
|
||||
\c false, the \a value is not inserted. Else if \l isOrdered() returns
|
||||
\c false, the \a value is not inserted. Else if \l isSortable() returns
|
||||
\c true, the value is inserted before the value pointed to by
|
||||
\a iterator. Else, the \a value is inserted at an unspecified place or not
|
||||
at all. In the latter case, the \a iterator is taken as a hint. If it points
|
||||
to the correct place for the \a value, the operation may be faster than a
|
||||
\l addValue() without iterator.
|
||||
|
||||
\sa canInsertValueAtIterator(), isOrdered(), begin(), end()
|
||||
\sa canInsertValueAtIterator(), isSortable(), begin(), end()
|
||||
*/
|
||||
void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
|
||||
const void *value) const
|
||||
|
|
|
|||
|
|
@ -59,15 +59,24 @@ enum IteratorCapability : quint8 {
|
|||
Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
|
||||
|
||||
enum AddRemoveCapability : quint8 {
|
||||
CanAddAtBegin = 1 << 0,
|
||||
CanRemoveAtBegin = 1 << 1,
|
||||
CanAddAtEnd = 1 << 2,
|
||||
CanRemoveAtEnd = 1 << 3
|
||||
};
|
||||
Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
|
||||
|
||||
class QMetaSequenceInterface
|
||||
{
|
||||
public:
|
||||
enum Position : quint8 { AtBegin, AtEnd, Random };
|
||||
enum Position : quint8 { AtBegin, AtEnd, Unspecified };
|
||||
|
||||
ushort revision;
|
||||
IteratorCapabilities iteratorCapabilities;
|
||||
Position addRemovePosition;
|
||||
QMetaType valueMetaType;
|
||||
AddRemoveCapabilities addRemoveCapabilities;
|
||||
|
||||
using SizeFn = qsizetype(*)(const void *);
|
||||
SizeFn sizeFn;
|
||||
|
|
@ -79,9 +88,9 @@ public:
|
|||
using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
|
||||
SetValueAtIndexFn setValueAtIndexFn;
|
||||
|
||||
using AddValueFn = void(*)(void *, const void *);
|
||||
using AddValueFn = void(*)(void *, const void *, Position);
|
||||
AddValueFn addValueFn;
|
||||
using RemoveValueFn = void(*)(void *);
|
||||
using RemoveValueFn = void(*)(void *, Position);
|
||||
RemoveValueFn removeValueFn;
|
||||
|
||||
using CreateIteratorFn = void *(*)(void *, Position);
|
||||
|
|
@ -144,13 +153,18 @@ class QMetaSequenceForContainer
|
|||
return {};
|
||||
}
|
||||
|
||||
static constexpr QMetaSequenceInterface::Position getAddRemovePosition()
|
||||
static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_push_back_v<C> && QContainerTraits::has_pop_back_v<C>)
|
||||
return QMetaSequenceInterface::AtEnd;
|
||||
if constexpr (QContainerTraits::has_push_front_v<C> && QContainerTraits::has_pop_front_v<C>)
|
||||
return QMetaSequenceInterface::AtBegin;
|
||||
return QMetaSequenceInterface::Random;
|
||||
AddRemoveCapabilities caps;
|
||||
if constexpr (QContainerTraits::has_push_back_v<C>)
|
||||
caps |= CanAddAtEnd;
|
||||
if constexpr (QContainerTraits::has_pop_back_v<C>)
|
||||
caps |= CanRemoveAtEnd;
|
||||
if constexpr (QContainerTraits::has_push_front_v<C>)
|
||||
caps |= CanAddAtBegin;
|
||||
if constexpr (QContainerTraits::has_pop_front_v<C>)
|
||||
caps |= CanRemoveAtBegin;
|
||||
return caps;
|
||||
}
|
||||
|
||||
static constexpr QMetaType getValueMetaType()
|
||||
|
|
@ -208,19 +222,49 @@ class QMetaSequenceForContainer
|
|||
static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_push_back_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->push_back(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
};
|
||||
if constexpr (QContainerTraits::has_push_front_v<C>) {
|
||||
return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
|
||||
const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
static_cast<C *>(c)->push_front(value);
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
static_cast<C *>(c)->push_back(value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
|
||||
const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
static_cast<C *>(c)->push_back(value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if constexpr (QContainerTraits::has_push_front_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->push_front(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
|
||||
const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
static_cast<C *>(c)->push_front(value);
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
break;
|
||||
}
|
||||
};
|
||||
} else if constexpr (QContainerTraits::has_insert_v<C>) {
|
||||
return [](void *c, const void *v) {
|
||||
static_cast<C *>(c)->insert(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
|
||||
if (position == QMetaSequenceInterface::Unspecified) {
|
||||
static_cast<C *>(c)->insert(
|
||||
*static_cast<const QContainerTraits::value_type<C> *>(v));
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
|
|
@ -230,9 +274,41 @@ class QMetaSequenceForContainer
|
|||
static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_pop_back_v<C>) {
|
||||
return [](void *c) { static_cast<C *>(c)->pop_back(); };
|
||||
if constexpr (QContainerTraits::has_pop_front_v<C>) {
|
||||
return [](void *c, QMetaSequenceInterface::Position position) {
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
static_cast<C *>(c)->pop_front();
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
static_cast<C *>(c)->pop_back();
|
||||
break;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return [](void *c, QMetaSequenceInterface::Position position) {
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
break;
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
static_cast<C *>(c)->pop_back();
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if constexpr (QContainerTraits::has_pop_front_v<C>) {
|
||||
return [](void *c) { static_cast<C *>(c)->pop_front(); };
|
||||
return [](void *c, QMetaSequenceInterface::Position position) {
|
||||
switch (position) {
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
static_cast<C *>(c)->pop_front();
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
break;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -245,7 +321,7 @@ class QMetaSequenceForContainer
|
|||
using Iterator = QContainerTraits::iterator<C>;
|
||||
switch (p) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
case QMetaSequenceInterface::Random:
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
return new Iterator(static_cast<C *>(c)->begin());
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
|
|
@ -377,7 +453,7 @@ class QMetaSequenceForContainer
|
|||
using Iterator = QContainerTraits::const_iterator<C>;
|
||||
switch (p) {
|
||||
case QMetaSequenceInterface::AtBegin:
|
||||
case QMetaSequenceInterface::Random:
|
||||
case QMetaSequenceInterface::Unspecified:
|
||||
return new Iterator(static_cast<const C *>(c)->begin());
|
||||
break;
|
||||
case QMetaSequenceInterface::AtEnd:
|
||||
|
|
@ -471,8 +547,8 @@ template<typename C>
|
|||
QMetaSequenceInterface QMetaSequenceForContainer<C>::metaSequence = {
|
||||
/*.revision=*/ 0,
|
||||
/*.iteratorCapabilities=*/ getIteratorCapabilities(),
|
||||
/*.addRemovePosition=*/ getAddRemovePosition(),
|
||||
/*.valueMetaType=*/ getValueMetaType(),
|
||||
/*.addRemoveCapabilities=*/ getAddRemoveCapabilities(),
|
||||
/*.sizeFn=*/ getSizeFn(),
|
||||
/*.clearFn=*/ getClearFn(),
|
||||
/*.valueAtIndexFn=*/ getValueAtIndexFn(),
|
||||
|
|
@ -525,9 +601,15 @@ public:
|
|||
|
||||
QMetaType valueMetaType() const;
|
||||
|
||||
bool isOrdered() const;
|
||||
bool addsAndRemovesValuesAtBegin() const;
|
||||
bool addsAndRemovesValuesAtEnd() const;
|
||||
bool isSortable() const;
|
||||
bool canAddValueAtBegin() const;
|
||||
void addValueAtBegin(void *container, const void *value) const;
|
||||
bool canAddValueAtEnd() const;
|
||||
void addValueAtEnd(void *container, const void *value) const;
|
||||
bool canRemoveValueAtBegin() const;
|
||||
void removeValueAtBegin(void *container) const;
|
||||
bool canRemoveValueAtEnd() const;
|
||||
void removeValueAtEnd(void *container) const;
|
||||
|
||||
bool hasSize() const;
|
||||
qsizetype size(const void *container) const;
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ void tst_QMetaContainer::testSequence_data()
|
|||
QTest::addColumn<bool>("hasRandomAccessIterator");
|
||||
QTest::addColumn<bool>("canInsertAtIterator");
|
||||
QTest::addColumn<bool>("canEraseAtIterator");
|
||||
QTest::addColumn<bool>("isOrdered");
|
||||
QTest::addColumn<bool>("isSortable");
|
||||
|
||||
QTest::addRow("QVector")
|
||||
<< static_cast<void *>(&qvector)
|
||||
|
|
@ -256,7 +256,7 @@ void tst_QMetaContainer::testSequence()
|
|||
QFETCH(bool, hasRandomAccessIterator);
|
||||
QFETCH(bool, canInsertAtIterator);
|
||||
QFETCH(bool, canEraseAtIterator);
|
||||
QFETCH(bool, isOrdered);
|
||||
QFETCH(bool, isSortable);
|
||||
|
||||
QVERIFY(metaSequence.canAddValue());
|
||||
QCOMPARE(metaSequence.hasSize(), hasSize);
|
||||
|
|
@ -267,7 +267,7 @@ void tst_QMetaContainer::testSequence()
|
|||
QCOMPARE(metaSequence.hasRandomAccessIterator(), hasRandomAccessIterator);
|
||||
QCOMPARE(metaSequence.canInsertValueAtIterator(), canInsertAtIterator);
|
||||
QCOMPARE(metaSequence.canEraseValueAtIterator(), canEraseAtIterator);
|
||||
QCOMPARE(metaSequence.isOrdered(), isOrdered);
|
||||
QCOMPARE(metaSequence.isSortable(), isSortable);
|
||||
|
||||
QVariant var1(metaType);
|
||||
QVariant var2(metaType);
|
||||
|
|
@ -434,7 +434,7 @@ void tst_QMetaContainer::testSequence()
|
|||
|
||||
const qsizetype newSize = metaSequence.diffIterator(end, it);
|
||||
|
||||
if (metaSequence.isOrdered()) {
|
||||
if (metaSequence.isSortable()) {
|
||||
QCOMPARE(newSize, size + 3);
|
||||
QVariant var4(metaType);
|
||||
metaSequence.valueAtIterator(it, var4.data());
|
||||
|
|
|
|||
|
|
@ -4539,7 +4539,8 @@ void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
|
|||
[](const void *, QtMetaContainerPrivate::QMetaSequenceInterface::Position) -> void* {
|
||||
return nullptr;
|
||||
};
|
||||
metaSequence.addValueFn = [](void *, const void *) {};
|
||||
metaSequence.addValueFn = [](void *, const void *,
|
||||
QtMetaContainerPrivate::QMetaSequenceInterface::Position) {};
|
||||
metaSequence.advanceConstIteratorFn = [](void *, qsizetype) {};
|
||||
metaSequence.destroyConstIteratorFn = [](const void *){};
|
||||
metaSequence.compareConstIteratorFn = [](const void *, const void *) {
|
||||
|
|
@ -4697,10 +4698,19 @@ void tst_QVariant::sequentialIterableAppend()
|
|||
QVERIFY(variant.canConvert<QSequentialIterable>());
|
||||
auto asIterable = variant.value<QSequentialIterable>();
|
||||
const int i = 3, j = 4;
|
||||
void *mutableIterable = const_cast<void *>(asIterable.constIterable());
|
||||
asIterable.metaSequence().addValue(mutableIterable, &i);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &j);
|
||||
void *mutableIterable = asIterable.mutableIterable();
|
||||
asIterable.metaSequence().addValueAtEnd(mutableIterable, &i);
|
||||
asIterable.metaSequence().addValueAtEnd(mutableIterable, &j);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 1, 2, 3, 4 }));
|
||||
|
||||
asIterable.metaSequence().addValueAtBegin(mutableIterable, &i);
|
||||
asIterable.metaSequence().addValueAtBegin(mutableIterable, &j);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 4, 3, 1, 2, 3, 4 }));
|
||||
|
||||
asIterable.metaSequence().removeValueAtBegin(mutableIterable);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 3, 1, 2, 3, 4 }));
|
||||
asIterable.metaSequence().removeValueAtEnd(mutableIterable);
|
||||
QCOMPARE(variant.value<QList<int>>(), QList<int> ({ 3, 1, 2, 3 }));
|
||||
}
|
||||
{
|
||||
QSet<QByteArray> container { QByteArray{"hello"}, QByteArray{"world"} };
|
||||
|
|
@ -4709,11 +4719,14 @@ void tst_QVariant::sequentialIterableAppend()
|
|||
auto asIterable = variant.value<QSequentialIterable>();
|
||||
QByteArray qba1 {"goodbye"};
|
||||
QByteArray qba2 { "moon" };
|
||||
void *mutableIterable = const_cast<void *>(asIterable.constIterable());
|
||||
void *mutableIterable = asIterable.mutableIterable();
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba2);
|
||||
QSet<QByteArray> reference { "hello", "world", "goodbye", "moon" };
|
||||
QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba1);
|
||||
asIterable.metaSequence().addValue(mutableIterable, &qba2);
|
||||
QCOMPARE(variant.value<QSet<QByteArray>>(), reference);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue