Skip to content

Commit

Permalink
QByteArrayList: add indexOf(const char*) overload
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dfaure-kdab committed Nov 6, 2018
1 parent a76f8ca commit fc88dd5
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/corelib/tools/qbytearraylist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions src/corelib/tools/qbytearraylist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -76,6 +77,9 @@ template <> struct QListSpecialMethods<QByteArray>
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); }
Expand Down
26 changes: 26 additions & 0 deletions tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit fc88dd5

Please sign in to comment.