QByteArray: deduplicate QtPrivate::findByteArray() and qFindByteArray()

The former is the only place where the latter is called and both were
doing duplicate and redudant work. So merge the two functions again...
and split off the actual hashed searching into a new qFindByteArray.
That simplifies the diff and Git history.

Drive-by adding the Q_NEVER_INLINE to the Boyer-Moore search, which will
be reached via tail-call.

Task-number: QTBUG-125283
Change-Id: If05cb740b64f42eba21efffd17cf2ed2bbc64b17
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
bb10
Thiago Macieira 2024-05-13 16:04:25 -07:00
parent eeb6f0337e
commit 7200f8638c
2 changed files with 15 additions and 33 deletions

View File

@ -56,10 +56,6 @@ static constexpr inline uchar asciiLower(uchar c)
return c >= 'A' && c <= 'Z' ? c | 0x20 : c;
}
qsizetype qFindByteArray(
const char *haystack0, qsizetype haystackLen, qsizetype from,
const char *needle0, qsizetype needleLen);
/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
@ -2685,26 +2681,6 @@ QByteArray QByteArray::repeated(qsizetype times) const
hashHaystack -= std::size_t(a) << ol_minus_1; \
hashHaystack <<= 1
qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
const auto ol = needle.size();
const auto l = haystack.size();
if (ol == 0) {
if (from < 0)
return qMax(from + l, 0);
else
return from > l ? -1 : from;
}
if (ol == 1)
return findByteArray(haystack, from, needle.front());
if (from > l || ol + from > l)
return -1;
return qFindByteArray(haystack.data(), haystack.size(), from, needle.data(), ol);
}
/*! \fn qsizetype QByteArray::indexOf(QByteArrayView bv, qsizetype from) const
\since 6.0

View File

@ -215,6 +215,7 @@ qsizetype QByteArrayMatcher::indexIn(QByteArrayView data, qsizetype from) const
/*!
\internal
*/
Q_NEVER_INLINE
static qsizetype qFindByteArrayBoyerMoore(
const char *haystack, qsizetype haystackLen, qsizetype haystackOffset,
const char *needle, qsizetype needleLen)
@ -235,12 +236,13 @@ static qsizetype qFindByteArrayBoyerMoore(
/*!
\internal
*/
qsizetype qFindByteArray(
const char *haystack0, qsizetype haystackLen, qsizetype from,
const char *needle, qsizetype needleLen)
static qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
const char *needle, qsizetype sl);
qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
const auto l = haystackLen;
const auto sl = needleLen;
const auto haystack0 = haystack.data();
const auto l = haystack.size();
const auto sl = needle.size();
if (from < 0)
from += l;
if (std::size_t(sl + from) > std::size_t(l))
@ -251,7 +253,7 @@ qsizetype qFindByteArray(
return -1;
if (sl == 1)
return QtPrivate::findByteArray({ haystack0, haystackLen }, from, needle[0]);
return findByteArray(haystack, from, needle.front());
/*
We use the Boyer-Moore algorithm in cases where the overhead
@ -259,13 +261,17 @@ qsizetype qFindByteArray(
hash function.
*/
if (l > 500 && sl > 5)
return qFindByteArrayBoyerMoore(haystack0, haystackLen, from,
needle, needleLen);
return qFindByteArrayBoyerMoore(haystack0, l, from, needle.data(), sl);
return qFindByteArray(haystack0, l, from, needle.data(), sl);
}
qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
const char *needle, qsizetype sl)
{
/*
We use some hashing for efficiency's sake. Instead of
comparing strings, we compare the hash value of str with that
of a part of this QString. Only if that matches, we call memcmp().
of a part of this QByteArray. Only if that matches, we call memcmp().
*/
const char *haystack = haystack0 + from;
const char *end = haystack0 + (l - sl);