QREMatchIterator: add support for range-based for
Add begin()/end() on QRegularExpressionMatchIterator, making iterators over an iterator (like directory_iterator). [ChangeLog][QtCore][QRegularExpression] The iterator object (QRegularExpressionMatchIterator) returned by a global match is now usable in a range-based for loop. Change-Id: If3d31bd2e84e7d1fb626a0b3d2745914dff03e39 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
cc692bb58c
commit
7ee682a1dd
|
|
@ -355,4 +355,13 @@ QString wildcard = QRegularExpression::wildcardToRegularExpression("*.jpeg");
|
|||
("", "day", "month", "year", "", "name")
|
||||
//! [33]
|
||||
|
||||
{
|
||||
//! [34]
|
||||
QRegularExpression re(R"(\w+)");
|
||||
QString subject("the quick fox");
|
||||
for (const QRegularExpressionMatch &match : re.globalMatch(subject)) {
|
||||
// ...
|
||||
}
|
||||
//! [34]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,6 +260,12 @@ QT_BEGIN_NAMESPACE
|
|||
You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get
|
||||
the next result without advancing the iterator.
|
||||
|
||||
It is also possible to simply use the result of
|
||||
QRegularExpression::globalMatch in a range-based for loop, for instance
|
||||
like this:
|
||||
|
||||
\snippet code/src_corelib_text_qregularexpression.cpp 34
|
||||
|
||||
It is possible to pass a starting offset and one or more match options to
|
||||
the globalMatch() function, exactly like normal matching with match().
|
||||
|
||||
|
|
@ -535,6 +541,12 @@ QT_BEGIN_NAMESPACE
|
|||
Moreover, QRegularExpressionMatchIterator offers a peekNext() function
|
||||
to get the next result \e{without} advancing the iterator.
|
||||
|
||||
Starting with Qt 6.0, it is also possible to simply use the result of
|
||||
QRegularExpression::globalMatch in a range-based for loop, for instance
|
||||
like this:
|
||||
|
||||
\snippet code/src_corelib_text_qregularexpression.cpp 34
|
||||
|
||||
You can retrieve the QRegularExpression object the subject string was
|
||||
matched against by calling the regularExpression() function; the
|
||||
match type and the match options are available as well by calling
|
||||
|
|
@ -2563,6 +2575,19 @@ QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions()
|
|||
return d->matchOptions;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
|
||||
{
|
||||
return QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator(iterator);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &)
|
||||
\internal
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
/*!
|
||||
\relates QRegularExpression
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#include <QtCore/qshareddata.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
QT_REQUIRE_CONFIG(regularexpression);
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -266,6 +268,11 @@ Q_DECLARE_SHARED(QRegularExpressionMatch)
|
|||
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match);
|
||||
#endif
|
||||
|
||||
namespace QtPrivate {
|
||||
class QRegularExpressionMatchIteratorRangeBasedForIterator;
|
||||
class QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel {};
|
||||
}
|
||||
|
||||
struct QRegularExpressionMatchIteratorPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QRegularExpressionMatchIterator
|
||||
|
|
@ -291,11 +298,100 @@ public:
|
|||
|
||||
private:
|
||||
friend class QRegularExpression;
|
||||
friend Q_CORE_EXPORT QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator);
|
||||
friend QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &) { return {}; }
|
||||
|
||||
QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd);
|
||||
QSharedDataPointer<QRegularExpressionMatchIteratorPrivate> d;
|
||||
};
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
// support for range-based for loop
|
||||
class QRegularExpressionMatchIteratorRangeBasedForIterator
|
||||
{
|
||||
public:
|
||||
using value_type = QRegularExpressionMatch;
|
||||
using difference_type = int;
|
||||
using reference_type = const QRegularExpressionMatch &;
|
||||
using pointer_type = const QRegularExpressionMatch *;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
QRegularExpressionMatchIteratorRangeBasedForIterator()
|
||||
: m_atEnd(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit QRegularExpressionMatchIteratorRangeBasedForIterator(const QRegularExpressionMatchIterator &iterator)
|
||||
: m_matchIterator(iterator),
|
||||
m_currentMatch(),
|
||||
m_atEnd(false)
|
||||
{
|
||||
++*this;
|
||||
}
|
||||
|
||||
const QRegularExpressionMatch &operator*() const
|
||||
{
|
||||
Q_ASSERT_X(!m_atEnd, Q_FUNC_INFO, "operator* called on an iterator already at the end");
|
||||
return m_currentMatch;
|
||||
}
|
||||
|
||||
QRegularExpressionMatchIteratorRangeBasedForIterator &operator++()
|
||||
{
|
||||
Q_ASSERT_X(!m_atEnd, Q_FUNC_INFO, "operator++ called on an iterator already at the end");
|
||||
if (m_matchIterator.hasNext()) {
|
||||
m_currentMatch = m_matchIterator.next();
|
||||
} else {
|
||||
m_currentMatch = QRegularExpressionMatch();
|
||||
m_atEnd = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QRegularExpressionMatchIteratorRangeBasedForIterator operator++(int)
|
||||
{
|
||||
QRegularExpressionMatchIteratorRangeBasedForIterator i = *this;
|
||||
++*this;
|
||||
return i;
|
||||
}
|
||||
|
||||
private:
|
||||
// [input.iterators] imposes operator== on us. Unfortunately, it's not
|
||||
// trivial to implement, so just do the bare minimum to satifisfy
|
||||
// Cpp17EqualityComparable.
|
||||
friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
|
||||
const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
|
||||
{
|
||||
return (&lhs == &rhs);
|
||||
}
|
||||
|
||||
friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
|
||||
const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// This is what we really use in a range-based for.
|
||||
friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
|
||||
QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
|
||||
{
|
||||
return lhs.m_atEnd;
|
||||
}
|
||||
|
||||
friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
|
||||
QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
|
||||
{
|
||||
return !lhs.m_atEnd;
|
||||
}
|
||||
|
||||
QRegularExpressionMatchIterator m_matchIterator;
|
||||
QRegularExpressionMatch m_currentMatch;
|
||||
bool m_atEnd;
|
||||
};
|
||||
|
||||
} // namespace QtPrivate
|
||||
|
||||
Q_DECLARE_SHARED(QRegularExpressionMatchIterator)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -184,6 +184,27 @@ bool operator==(const QRegularExpressionMatchIterator &iterator, const QList<Mat
|
|||
if (i.hasNext())
|
||||
return false;
|
||||
|
||||
i = iterator;
|
||||
|
||||
int index = 0;
|
||||
for (const QRegularExpressionMatch &match : i) {
|
||||
if (match != expectedMatchList[index++])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index != expectedMatchList.size())
|
||||
return false;
|
||||
|
||||
// do it again
|
||||
index = 0;
|
||||
for (const QRegularExpressionMatch &match : i) {
|
||||
if (match != expectedMatchList[index++])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index != expectedMatchList.size())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue