QByteArrayList: add indexOf(const char*) overload

This avoids memory allocation and data copying in e.g.
QObject::property().

Detected by heaptrack's "Temporary allocations" counter in an
application using the breeze widget style (many animations).

Change-Id: Iabdb58a3e504cb121cce906ef707b0722de89df6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
David Faure 2018-10-25 11:07:58 +02:00
parent a76f8caf29
commit fc88dd52a4
3 changed files with 52 additions and 0 deletions

View File

@ -150,4 +150,26 @@ QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char
return res;
}
/*!
\fn int QByteArrayList::indexOf(const char *needle, int from) const
Returns the index position of the first occurrence of \a needle in
the list, searching forward from index position \a from. Returns
-1 if no item matched.
\a needle must be NUL-terminated.
This overload doesn't require creating a QByteArray, thus saving a
memory allocation and some CPU time.
\since 5.13
\overload
*/
int QtPrivate::QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from)
{
const auto it = std::find_if(that->begin() + from, that->end(), [needle](const QByteArray &item) { return item == needle; });
return it == that->end() ? -1 : int(std::distance(that->begin(), it));
}
QT_END_NAMESPACE

View File

@ -55,6 +55,7 @@ typedef QList<QByteArray> QByteArrayList;
namespace QtPrivate {
QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength);
int Q_CORE_EXPORT QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from);
}
#endif
@ -76,6 +77,9 @@ public:
inline QByteArray join(char sep) const
{ return QtPrivate::QByteArrayList_join(self(), &sep, 1); }
inline int indexOf(const char *needle, int from = 0) const
{ return QtPrivate::QByteArrayList_indexOf(self(), needle, from); }
private:
typedef QList<QByteArray> Self;
Self *self() { return static_cast<Self *>(this); }

View File

@ -49,6 +49,9 @@ private slots:
void operator_plus() const;
void operator_plus_data() const;
void indexOf_data() const;
void indexOf() const;
void initializerList() const;
};
@ -259,6 +262,29 @@ void tst_QByteArrayList::operator_plus_data() const
<< ( QByteArrayList() << "a" << "" << "c" );
}
void tst_QByteArrayList::indexOf_data() const
{
QTest::addColumn<QByteArrayList>("list");
QTest::addColumn<QByteArray>("item");
QTest::addColumn<int>("expectedResult");
QTest::newRow("empty") << QByteArrayList() << QByteArray("a") << -1;
QTest::newRow("found_1") << ( QByteArrayList() << "a" ) << QByteArray("a") << 0;
QTest::newRow("not_found_1") << ( QByteArrayList() << "a" ) << QByteArray("b") << -1;
QTest::newRow("found_2") << ( QByteArrayList() << "hello" << "world" ) << QByteArray("world") << 1;
QTest::newRow("returns_first") << ( QByteArrayList() << "hello" << "world" << "hello" << "again" ) << QByteArray("hello") << 0;
}
void tst_QByteArrayList::indexOf() const
{
QFETCH(QByteArrayList, list);
QFETCH(QByteArray, item);
QFETCH(int, expectedResult);
QCOMPARE(list.indexOf(item), expectedResult);
QCOMPARE(list.indexOf(item.constData()), expectedResult);
}
void tst_QByteArrayList::initializerList() const
{
#ifdef Q_COMPILER_INITIALIZER_LISTS