qstringalgorithms: add find methods
Also add qsizetype support. It's needed to add find methods to QStringView Change-Id: I45eac082924e27778c24eebbb19d694221c28978 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
3b38c73c7f
commit
68d75aef76
@ -58,9 +58,6 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
int qFindString(const QChar *haystack, int haystackLen, int from,
|
||||
const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
|
||||
|
||||
// error strings for the regexp parser
|
||||
#define RXERR_OK QT_TRANSLATE_NOOP("QRegExp", "no error occurred")
|
||||
#define RXERR_DISABLED QT_TRANSLATE_NOOP("QRegExp", "disabled feature used")
|
||||
@ -1423,7 +1420,8 @@ void QRegExpMatchState::match(const QChar *str0, int len0, int pos0,
|
||||
|
||||
#ifndef QT_NO_REGEXP_OPTIM
|
||||
if (eng->trivial && !oneTest) {
|
||||
pos = qFindString(str0, len0, pos0, eng->goodStr.unicode(), eng->goodStr.length(), eng->cs);
|
||||
// ### Qt6: qsize
|
||||
pos = int(QtPrivate::findString(QStringView(str0, len0), pos0, QStringView(eng->goodStr.unicode(), eng->goodStr.length()), eng->cs));
|
||||
matchLen = eng->goodStr.length();
|
||||
matched = (pos != -1);
|
||||
} else
|
||||
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Copyright (C) 2019 Mail.ru Group.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -142,19 +143,11 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int leng
|
||||
#endif
|
||||
|
||||
// internal
|
||||
int qFindString(const QChar *haystack, int haystackLen, int from,
|
||||
const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
|
||||
int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from,
|
||||
const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
|
||||
static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle,
|
||||
int from, Qt::CaseSensitivity cs);
|
||||
static inline int qt_string_count(const QChar *haystack, int haystackLen,
|
||||
const QChar *needle, int needleLen,
|
||||
Qt::CaseSensitivity cs);
|
||||
static inline int qt_string_count(const QChar *haystack, int haystackLen,
|
||||
QChar needle, Qt::CaseSensitivity cs);
|
||||
static inline int qt_find_latin1_string(const QChar *hay, int size, QLatin1String needle,
|
||||
int from, Qt::CaseSensitivity cs);
|
||||
qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
|
||||
static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs);
|
||||
static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
|
||||
static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
|
||||
|
||||
static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
|
||||
static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
|
||||
static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
|
||||
@ -1283,42 +1276,9 @@ int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens
|
||||
return qt_compare_strings(lhs, rhs, cs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns the index position of the first occurrence of the
|
||||
character \a ch in the string given by \a str and \a len,
|
||||
searching forward from index
|
||||
position \a from. Returns -1 if \a ch could not be found.
|
||||
*/
|
||||
static int findChar(const QChar *str, int len, QChar ch, int from,
|
||||
Qt::CaseSensitivity cs)
|
||||
{
|
||||
const ushort *s = (const ushort *)str;
|
||||
ushort c = ch.unicode();
|
||||
if (from < 0)
|
||||
from = qMax(from + len, 0);
|
||||
if (from < len) {
|
||||
const ushort *n = s + from;
|
||||
const ushort *e = s + len;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
n = QtPrivate::qustrchr(QStringView(n, e), c);
|
||||
if (n != e)
|
||||
return n - s;
|
||||
} else {
|
||||
c = foldCase(c);
|
||||
--n;
|
||||
while (++n != e)
|
||||
if (foldCase(*n) == c)
|
||||
return n - s;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define REHASH(a) \
|
||||
if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \
|
||||
hashHaystack -= uint(a) << sl_minus_1; \
|
||||
if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
|
||||
hashHaystack -= std::size_t(a) << sl_minus_1; \
|
||||
hashHaystack <<= 1
|
||||
|
||||
inline bool qIsUpper(char ch)
|
||||
@ -3735,7 +3695,8 @@ bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW
|
||||
*/
|
||||
int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3759,85 +3720,8 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
|
||||
|
||||
int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_find_latin1_string(unicode(), size(), str, from, cs);
|
||||
}
|
||||
|
||||
int qFindString(
|
||||
const QChar *haystack0, int haystackLen, int from,
|
||||
const QChar *needle0, int needleLen, Qt::CaseSensitivity cs)
|
||||
{
|
||||
const int l = haystackLen;
|
||||
const int sl = needleLen;
|
||||
if (from < 0)
|
||||
from += l;
|
||||
if (uint(sl + from) > (uint)l)
|
||||
return -1;
|
||||
if (!sl)
|
||||
return from;
|
||||
if (!l)
|
||||
return -1;
|
||||
|
||||
if (sl == 1)
|
||||
return findChar(haystack0, haystackLen, needle0[0], from, cs);
|
||||
|
||||
/*
|
||||
We use the Boyer-Moore algorithm in cases where the overhead
|
||||
for the skip table should pay off, otherwise we use a simple
|
||||
hash function.
|
||||
*/
|
||||
if (l > 500 && sl > 5)
|
||||
return qFindStringBoyerMoore(haystack0, haystackLen, from,
|
||||
needle0, needleLen, cs);
|
||||
|
||||
auto sv = [sl](const ushort *v) { return QStringView(v, 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
|
||||
qt_string_compare().
|
||||
*/
|
||||
const ushort *needle = (const ushort *)needle0;
|
||||
const ushort *haystack = (const ushort *)haystack0 + from;
|
||||
const ushort *end = (const ushort *)haystack0 + (l-sl);
|
||||
const uint sl_minus_1 = sl - 1;
|
||||
uint hashNeedle = 0, hashHaystack = 0;
|
||||
int idx;
|
||||
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = ((hashNeedle<<1) + needle[idx]);
|
||||
hashHaystack = ((hashHaystack<<1) + haystack[idx]);
|
||||
}
|
||||
hashHaystack -= haystack[sl_minus_1];
|
||||
|
||||
while (haystack <= end) {
|
||||
hashHaystack += haystack[sl_minus_1];
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
|
||||
return haystack - (const ushort *)haystack0;
|
||||
|
||||
REHASH(*haystack);
|
||||
++haystack;
|
||||
}
|
||||
} else {
|
||||
const ushort *haystack_start = (const ushort *)haystack0;
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle);
|
||||
hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start);
|
||||
}
|
||||
hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start);
|
||||
|
||||
while (haystack <= end) {
|
||||
hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(sv(needle), sv(haystack), Qt::CaseInsensitive) == 0)
|
||||
return haystack - (const ushort *)haystack0;
|
||||
|
||||
REHASH(foldCase(haystack, haystack_start));
|
||||
++haystack;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3849,7 +3733,8 @@ int qFindString(
|
||||
*/
|
||||
int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return findChar(unicode(), length(), ch, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3866,7 +3751,8 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
|
||||
}
|
||||
|
||||
static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs)
|
||||
@ -3989,7 +3875,8 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co
|
||||
*/
|
||||
int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_last_index_of(unicode(), size(), ch, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4322,7 +4209,8 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
|
||||
|
||||
int QString::count(const QString &str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4338,8 +4226,9 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const
|
||||
|
||||
int QString::count(QChar ch, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), ch, cs);
|
||||
}
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), ch, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.8
|
||||
@ -4354,7 +4243,8 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
|
||||
}
|
||||
|
||||
|
||||
@ -7782,10 +7672,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep,
|
||||
QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize)
|
||||
{
|
||||
ResultList list;
|
||||
int start = 0;
|
||||
int end;
|
||||
int extra = 0;
|
||||
while ((end = qFindString(source.constData(), source.size(), start + extra, sep, separatorSize, cs)) != -1) {
|
||||
typename StringSource::size_type start = 0;
|
||||
typename StringSource::size_type end;
|
||||
typename StringSource::size_type extra = 0;
|
||||
while ((end = QtPrivate::findString(QStringView(source.constData(), source.size()), start + extra, QStringView(sep, separatorSize), cs)) != -1) {
|
||||
if (start != end || behavior == QString::KeepEmptyParts)
|
||||
list.append(source.mid(start, end - start));
|
||||
start = end + separatorSize;
|
||||
@ -11158,7 +11048,8 @@ QStringRef QString::midRef(int position, int n) const
|
||||
*/
|
||||
int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11173,7 +11064,8 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co
|
||||
*/
|
||||
int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return findChar(unicode(), length(), ch, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findChar(QStringView(unicode(), length()), ch, from, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11193,7 +11085,8 @@ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_find_latin1_string(unicode(), size(), str, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11212,7 +11105,8 @@ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) con
|
||||
*/
|
||||
int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11245,7 +11139,8 @@ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs
|
||||
*/
|
||||
int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_last_index_of(unicode(), size(), ch, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -11321,7 +11216,8 @@ int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity
|
||||
*/
|
||||
int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11338,7 +11234,8 @@ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), ch, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), ch, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11355,7 +11252,8 @@ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
|
||||
// ### Qt6: qsize
|
||||
return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11592,16 +11490,16 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
|
||||
\sa indexOf(), count()
|
||||
*/
|
||||
|
||||
static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle,
|
||||
int from, Qt::CaseSensitivity cs)
|
||||
static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle,
|
||||
qsizetype from, Qt::CaseSensitivity cs)
|
||||
{
|
||||
ushort c = needle.unicode();
|
||||
if (from < 0)
|
||||
from += haystackLen;
|
||||
if (uint(from) >= uint(haystackLen))
|
||||
from += haystack.size();
|
||||
if (std::size_t(from) >= std::size_t(haystack.size()))
|
||||
return -1;
|
||||
if (from >= 0) {
|
||||
const ushort *b = reinterpret_cast<const ushort*>(haystack);
|
||||
ushort c = needle.unicode();
|
||||
const ushort *b = reinterpret_cast<const ushort*>(haystack.data());
|
||||
const ushort *n = b + from;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (; n >= b; --n)
|
||||
@ -11619,30 +11517,28 @@ static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar
|
||||
|
||||
}
|
||||
|
||||
static inline int qt_string_count(const QChar *haystack, int haystackLen,
|
||||
const QChar *needle, int needleLen,
|
||||
Qt::CaseSensitivity cs)
|
||||
static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
int num = 0;
|
||||
int i = -1;
|
||||
if (haystackLen > 500 && needleLen > 5) {
|
||||
QStringMatcher matcher(needle, needleLen, cs);
|
||||
while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1)
|
||||
qsizetype num = 0;
|
||||
qsizetype i = -1;
|
||||
if (haystack.size() > 500 && needle.size() > 5) {
|
||||
QStringMatcher matcher(needle, cs);
|
||||
while ((i = matcher.indexIn(haystack, i + 1)) != -1)
|
||||
++num;
|
||||
} else {
|
||||
while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1)
|
||||
while ((i = QtPrivate::findString(haystack, i + 1, needle, cs)) != -1)
|
||||
++num;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static inline int qt_string_count(const QChar *unicode, int size, QChar ch,
|
||||
static inline qsizetype qt_string_count(QStringView haystack, QChar ch,
|
||||
Qt::CaseSensitivity cs)
|
||||
{
|
||||
ushort c = ch.unicode();
|
||||
int num = 0;
|
||||
const ushort *b = reinterpret_cast<const ushort*>(unicode);
|
||||
const ushort *i = b + size;
|
||||
qsizetype num = 0;
|
||||
const ushort *b = reinterpret_cast<const ushort*>(haystack.data());
|
||||
const ushort *i = b + haystack.size();
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
while (i != b)
|
||||
if (*--i == c)
|
||||
@ -11656,22 +11552,6 @@ static inline int qt_string_count(const QChar *unicode, int size, QChar ch,
|
||||
return num;
|
||||
}
|
||||
|
||||
static inline int qt_find_latin1_string(const QChar *haystack, int size,
|
||||
QLatin1String needle,
|
||||
int from, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (size < needle.size())
|
||||
return -1;
|
||||
|
||||
const char *latin1 = needle.latin1();
|
||||
int len = needle.size();
|
||||
QVarLengthArray<ushort> s(len);
|
||||
qt_from_latin1(s.data(), latin1, len);
|
||||
|
||||
return qFindString(haystack, size, from,
|
||||
reinterpret_cast<const QChar*>(s.constData()), len, cs);
|
||||
}
|
||||
|
||||
template <typename Haystack, typename Needle>
|
||||
bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
|
||||
{
|
||||
@ -11818,6 +11698,127 @@ bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseS
|
||||
return qt_ends_with_impl(haystack, needle, cs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns the index position of the first occurrence of the
|
||||
character \a ch in the string given by \a str and \a len,
|
||||
searching forward from index
|
||||
position \a from. Returns -1 if \a ch could not be found.
|
||||
*/
|
||||
|
||||
qsizetype QtPrivate::findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
|
||||
{
|
||||
if (from < 0)
|
||||
from = qMax(from + str.size(), qsizetype(0));
|
||||
if (from < str.size()) {
|
||||
const ushort *s = (const ushort *)str.data();
|
||||
ushort c = ch.unicode();
|
||||
const ushort *n = s + from;
|
||||
const ushort *e = s + str.size();
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
n = QtPrivate::qustrchr(QStringView(n, e), c);
|
||||
if (n != e)
|
||||
return n - s;
|
||||
} else {
|
||||
c = foldCase(c);
|
||||
--n;
|
||||
while (++n != e)
|
||||
if (foldCase(*n) == c)
|
||||
return n - s;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringView needle0, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
|
||||
{
|
||||
const qsizetype l = haystack0.size();
|
||||
const qsizetype sl = needle0.size();
|
||||
if (from < 0)
|
||||
from += l;
|
||||
if (std::size_t(sl + from) > std::size_t(l))
|
||||
return -1;
|
||||
if (!sl)
|
||||
return from;
|
||||
if (!l)
|
||||
return -1;
|
||||
|
||||
if (sl == 1)
|
||||
return QtPrivate::findChar(haystack0, needle0[0], from, cs);
|
||||
|
||||
/*
|
||||
We use the Boyer-Moore algorithm in cases where the overhead
|
||||
for the skip table should pay off, otherwise we use a simple
|
||||
hash function.
|
||||
*/
|
||||
if (l > 500 && sl > 5)
|
||||
return qFindStringBoyerMoore(haystack0, from, needle0, cs);
|
||||
|
||||
auto sv = [sl](const ushort *v) { return QStringView(v, 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
|
||||
qt_string_compare().
|
||||
*/
|
||||
const ushort *needle = (const ushort *)needle0.data();
|
||||
const ushort *haystack = (const ushort *)(haystack0.data()) + from;
|
||||
const ushort *end = (const ushort *)(haystack0.data()) + (l - sl);
|
||||
const std::size_t sl_minus_1 = sl - 1;
|
||||
std::size_t hashNeedle = 0, hashHaystack = 0;
|
||||
qsizetype idx;
|
||||
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = ((hashNeedle<<1) + needle[idx]);
|
||||
hashHaystack = ((hashHaystack<<1) + haystack[idx]);
|
||||
}
|
||||
hashHaystack -= haystack[sl_minus_1];
|
||||
|
||||
while (haystack <= end) {
|
||||
hashHaystack += haystack[sl_minus_1];
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
|
||||
return haystack - (const ushort *)haystack0.data();
|
||||
|
||||
REHASH(*haystack);
|
||||
++haystack;
|
||||
}
|
||||
} else {
|
||||
const ushort *haystack_start = (const ushort *)haystack0.data();
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle);
|
||||
hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start);
|
||||
}
|
||||
hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start);
|
||||
|
||||
while (haystack <= end) {
|
||||
hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(needle0, sv(haystack), Qt::CaseInsensitive) == 0)
|
||||
return haystack - (const ushort *)haystack0.data();
|
||||
|
||||
REHASH(foldCase(haystack, haystack_start));
|
||||
++haystack;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
|
||||
{
|
||||
if (haystack.size() < needle.size())
|
||||
return -1;
|
||||
|
||||
const char *latin1 = needle.latin1();
|
||||
const qsizetype len = needle.size();
|
||||
QVarLengthArray<ushort> s(len);
|
||||
qt_from_latin1(s.data(), latin1, len);
|
||||
|
||||
return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast<const QChar*>(s.constData()), len), cs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.8
|
||||
|
||||
|
@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QByteArray;
|
||||
class QLatin1String;
|
||||
class QStringView;
|
||||
class QChar;
|
||||
template <typename T> class QVector;
|
||||
|
||||
namespace QtPrivate {
|
||||
@ -74,6 +75,10 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) Q_DECL_NOTHROW;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) Q_DECL_NOTHROW;
|
||||
|
||||
|
@ -42,43 +42,43 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs)
|
||||
static void bm_init_skiptable(const ushort *uc, qsizetype len, uchar *skiptable, Qt::CaseSensitivity cs)
|
||||
{
|
||||
int l = qMin(len, 255);
|
||||
memset(skiptable, l, 256*sizeof(uchar));
|
||||
int l = int(qMin(len, qsizetype(255)));
|
||||
memset(skiptable, l, 256 * sizeof(uchar));
|
||||
uc += len - l;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
while (l--) {
|
||||
skiptable[*uc & 0xff] = l;
|
||||
uc++;
|
||||
++uc;
|
||||
}
|
||||
} else {
|
||||
const ushort *start = uc;
|
||||
while (l--) {
|
||||
skiptable[foldCase(uc, start) & 0xff] = l;
|
||||
uc++;
|
||||
++uc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl,
|
||||
static inline qsizetype bm_find(const ushort *uc, qsizetype l, qsizetype index, const ushort *puc, qsizetype pl,
|
||||
const uchar *skiptable, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (pl == 0)
|
||||
return index > (int)l ? -1 : index;
|
||||
const uint pl_minus_one = pl - 1;
|
||||
return index > l ? -1 : index;
|
||||
const qsizetype pl_minus_one = pl - 1;
|
||||
|
||||
const ushort *current = uc + index + pl_minus_one;
|
||||
const ushort *end = uc + l;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
while (current < end) {
|
||||
uint skip = skiptable[*current & 0xff];
|
||||
qsizetype skip = skiptable[*current & 0xff];
|
||||
if (!skip) {
|
||||
// possible match
|
||||
while (skip < pl) {
|
||||
if (*(current - skip) != puc[pl_minus_one-skip])
|
||||
break;
|
||||
skip++;
|
||||
++skip;
|
||||
}
|
||||
if (skip > pl_minus_one) // we have a match
|
||||
return (current - uc) - pl_minus_one;
|
||||
@ -96,13 +96,13 @@ static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc
|
||||
}
|
||||
} else {
|
||||
while (current < end) {
|
||||
uint skip = skiptable[foldCase(current, uc) & 0xff];
|
||||
qsizetype skip = skiptable[foldCase(current, uc) & 0xff];
|
||||
if (!skip) {
|
||||
// possible match
|
||||
while (skip < pl) {
|
||||
if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc))
|
||||
break;
|
||||
skip++;
|
||||
++skip;
|
||||
}
|
||||
if (skip > pl_minus_one) // we have a match
|
||||
return (current - uc) - pl_minus_one;
|
||||
@ -333,16 +333,16 @@ qsizetype QStringMatcher::indexIn(QStringView str, qsizetype from) const
|
||||
\internal
|
||||
*/
|
||||
|
||||
int qFindStringBoyerMoore(
|
||||
const QChar *haystack, int haystackLen, int haystackOffset,
|
||||
const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
|
||||
qsizetype qFindStringBoyerMoore(
|
||||
QStringView haystack, qsizetype haystackOffset,
|
||||
QStringView needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
uchar skiptable[256];
|
||||
bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs);
|
||||
bm_init_skiptable((const ushort *)needle.data(), needle.size(), skiptable, cs);
|
||||
if (haystackOffset < 0)
|
||||
haystackOffset = 0;
|
||||
return bm_find((const ushort *)haystack, haystackLen, haystackOffset,
|
||||
(const ushort *)needle, needleLen, skiptable, cs);
|
||||
return bm_find((const ushort *)haystack.data(), haystack.size(), haystackOffset,
|
||||
(const ushort *)needle.data(), needle.size(), skiptable, cs);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
Reference in New Issue
Block a user