QStringView, QLatin1String: add lastIndexOf methods
While touching the code, factor out internal methods to avoid needlees latin1->utf16 conversion. [ChangeLog][QtCore][QLatin1String] Added lastIndexOf(). [ChangeLog][QtCore][QStringView] Added lastIndexOf(). Change-Id: I1c624f00e4ed10111e0d00b86daff7904eeed176 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
eed9a8fbd3
commit
55240bcdf3
@ -145,7 +145,8 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int leng
|
||||
// internal
|
||||
qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
|
||||
static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept;
|
||||
static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs);
|
||||
template <typename Haystack>
|
||||
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
|
||||
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);
|
||||
|
||||
@ -3779,74 +3780,6 @@ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) co
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
|
||||
}
|
||||
#endif // QT_STRINGVIEW_LEVEL < 2
|
||||
|
||||
static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs)
|
||||
{
|
||||
/*
|
||||
See indexOf() for explanations.
|
||||
*/
|
||||
|
||||
auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
|
||||
|
||||
const ushort *end = haystack;
|
||||
haystack += from;
|
||||
const uint sl_minus_1 = sl - 1;
|
||||
const ushort *n = needle+sl_minus_1;
|
||||
const ushort *h = haystack+sl_minus_1;
|
||||
uint hashNeedle = 0, hashHaystack = 0;
|
||||
int idx;
|
||||
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = ((hashNeedle<<1) + *(n-idx));
|
||||
hashHaystack = ((hashHaystack<<1) + *(h-idx));
|
||||
}
|
||||
hashHaystack -= *haystack;
|
||||
|
||||
while (haystack >= end) {
|
||||
hashHaystack += *haystack;
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
|
||||
return haystack - end;
|
||||
--haystack;
|
||||
REHASH(haystack[sl]);
|
||||
}
|
||||
} else {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = ((hashNeedle<<1) + foldCase(n-idx, needle));
|
||||
hashHaystack = ((hashHaystack<<1) + foldCase(h-idx, end));
|
||||
}
|
||||
hashHaystack -= foldCase(haystack, end);
|
||||
|
||||
while (haystack >= end) {
|
||||
hashHaystack += foldCase(haystack, end);
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(sv(haystack), sv(needle), Qt::CaseInsensitive) == 0)
|
||||
return haystack - end;
|
||||
--haystack;
|
||||
REHASH(foldCase(haystack + sl, end));
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lastIndexOfHelper(
|
||||
const QStringRef &haystack, int from, const QStringRef &needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
return lastIndexOfHelper(reinterpret_cast<const ushort*>(haystack.unicode()), from,
|
||||
reinterpret_cast<const ushort*>(needle.unicode()), needle.size(), cs);
|
||||
}
|
||||
|
||||
static inline int lastIndexOfHelper(
|
||||
const QStringRef &haystack, int from, QLatin1String needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
const int size = needle.size();
|
||||
QVarLengthArray<ushort> s(size);
|
||||
qt_from_latin1(s.data(), needle.latin1(), size);
|
||||
return lastIndexOfHelper(reinterpret_cast<const ushort*>(haystack.unicode()), from,
|
||||
s.data(), size, cs);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index position of the last occurrence of the string \a
|
||||
@ -3866,9 +3799,12 @@ static inline int lastIndexOfHelper(
|
||||
*/
|
||||
int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return QStringRef(this).lastIndexOf(QStringRef(&str), from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
|
||||
#endif // QT_STRINGVIEW_LEVEL < 2
|
||||
|
||||
/*!
|
||||
\since 4.5
|
||||
\overload lastIndexOf()
|
||||
@ -3890,7 +3826,8 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c
|
||||
*/
|
||||
int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return QStringRef(this).lastIndexOf(str, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -3902,9 +3839,10 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co
|
||||
int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
// ### Qt6: qsize
|
||||
return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs));
|
||||
return int(qLastIndexOf(*this, ch, from, cs));
|
||||
}
|
||||
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
/*!
|
||||
\since 4.8
|
||||
\overload lastIndexOf()
|
||||
@ -3922,8 +3860,27 @@ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
*/
|
||||
int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return QStringRef(this).lastIndexOf(str, from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
#endif // QT_STRINGVIEW_LEVEL < 2
|
||||
|
||||
/*!
|
||||
\fn int QString::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
|
||||
\since 5.14
|
||||
\overload lastIndexOf()
|
||||
|
||||
Returns the index position of the last occurrence of the string view \a
|
||||
str in this string, searching backward from index position \a
|
||||
from. If \a from is -1 (default), the search starts at the last
|
||||
character; if \a from is -2, at the next to last character and so
|
||||
on. Returns -1 if \a str is not found.
|
||||
|
||||
If \a cs is Qt::CaseSensitive (default), the search is case
|
||||
sensitive; otherwise the search is case insensitive.
|
||||
|
||||
\sa indexOf(), contains(), count()
|
||||
*/
|
||||
|
||||
|
||||
#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression))
|
||||
@ -9560,6 +9517,24 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
||||
\sa indexOf(), QStringView::contains(), QStringView::indexOf(), QString::indexOf()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn int QLatin1String::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
|
||||
\fn int QLatin1String::lastIndexOf(QLatin1String l1, int from, Qt::CaseSensitivity cs) const
|
||||
\fn int QLatin1String::lastIndexOf(QChar c, int from, Qt::CaseSensitivity cs) const
|
||||
\since 5.14
|
||||
|
||||
Returns the index position of the last occurrence of the string-view \a str,
|
||||
Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string,
|
||||
searching backward from index position \a from. If \a from is -1 (default),
|
||||
the search starts at the last character; if \a from is -2, at the next to last
|
||||
character and so on. Returns -1 if \a str is not found.
|
||||
|
||||
If \a cs is Qt::CaseSensitive (default), the search is case
|
||||
sensitive; otherwise the search is case insensitive.
|
||||
|
||||
\sa indexOf(), QStringView::lastIndexOf(), QStringView::indexOf(), QString::indexOf()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QLatin1String::const_iterator QLatin1String::begin() const
|
||||
\since 5.10
|
||||
@ -11231,7 +11206,8 @@ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs)
|
||||
*/
|
||||
int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return lastIndexOf(QStringRef(&str), from, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11246,28 +11222,7 @@ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs
|
||||
int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
// ### Qt6: qsize
|
||||
return int(qt_last_index_of(QStringView(unicode(), size()), ch, from, cs));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static int last_index_of_impl(const QStringRef &haystack, int from, const T &needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
const int sl = needle.size();
|
||||
if (sl == 1)
|
||||
return haystack.lastIndexOf(needle.at(0), from, cs);
|
||||
|
||||
const int l = haystack.size();
|
||||
if (from < 0)
|
||||
from += l;
|
||||
int delta = l - sl;
|
||||
if (from == l && sl == 0)
|
||||
return from;
|
||||
if (uint(from) >= uint(l) || delta < 0)
|
||||
return -1;
|
||||
if (from > delta)
|
||||
from = delta;
|
||||
|
||||
return lastIndexOfHelper(haystack, from, needle, cs);
|
||||
return int(qLastIndexOf(*this, ch, from, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11287,7 +11242,8 @@ static int last_index_of_impl(const QStringRef &haystack, int from, const T &nee
|
||||
*/
|
||||
int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return last_index_of_impl(*this, from, str, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -11307,9 +11263,27 @@ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs)
|
||||
*/
|
||||
int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
|
||||
{
|
||||
return last_index_of_impl(*this, from, str, cs);
|
||||
// ### Qt6: qsize
|
||||
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int QStringRef::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
|
||||
\since 5.14
|
||||
\overload lastIndexOf()
|
||||
|
||||
Returns the index position of the last occurrence of the string view \a
|
||||
str in this string, searching backward from index position \a
|
||||
from. If \a from is -1 (default), the search starts at the last
|
||||
character; if \a from is -2, at the next to last character and so
|
||||
on. Returns -1 if \a str is not found.
|
||||
|
||||
If \a cs is Qt::CaseSensitive (default), the search is case
|
||||
sensitive; otherwise the search is case insensitive.
|
||||
|
||||
\sa indexOf(), contains(), count()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 4.8
|
||||
Returns the number of (potentially overlapping) occurrences of
|
||||
@ -11612,33 +11586,6 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
|
||||
\sa indexOf(), count()
|
||||
*/
|
||||
|
||||
static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle,
|
||||
qsizetype from, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (from < 0)
|
||||
from += haystack.size();
|
||||
if (std::size_t(from) >= std::size_t(haystack.size()))
|
||||
return -1;
|
||||
if (from >= 0) {
|
||||
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)
|
||||
if (*n == c)
|
||||
return n - b;
|
||||
} else {
|
||||
c = foldCase(c);
|
||||
for (; n >= b; --n)
|
||||
if (foldCase(*n) == c)
|
||||
return n - b;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
|
||||
{
|
||||
qsizetype num = 0;
|
||||
@ -11820,6 +11767,38 @@ bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseS
|
||||
return qt_ends_with_impl(haystack, needle, cs);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename Pointer>
|
||||
uint foldCaseHelper(Pointer ch, Pointer start) = delete;
|
||||
|
||||
template <>
|
||||
uint foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
|
||||
{
|
||||
return foldCase(reinterpret_cast<const ushort*>(ch), reinterpret_cast<const ushort*>(start));
|
||||
}
|
||||
|
||||
template <>
|
||||
uint foldCaseHelper<const char*>(const char* ch, const char*)
|
||||
{
|
||||
return foldCase(ushort(uchar(*ch)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ushort valueTypeToUtf16(T t) = delete;
|
||||
|
||||
template <>
|
||||
ushort valueTypeToUtf16<QChar>(QChar t)
|
||||
{
|
||||
return t.unicode();
|
||||
}
|
||||
|
||||
template <>
|
||||
ushort valueTypeToUtf16<char>(char t)
|
||||
{
|
||||
return ushort(uchar(t));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
@ -11928,6 +11907,97 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename Haystack>
|
||||
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
|
||||
qsizetype from, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
if (from < 0)
|
||||
from += haystack.size();
|
||||
if (std::size_t(from) >= std::size_t(haystack.size()))
|
||||
return -1;
|
||||
if (from >= 0) {
|
||||
ushort c = needle.unicode();
|
||||
const auto b = haystack.data();
|
||||
auto n = b + from;
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (; n >= b; --n)
|
||||
if (valueTypeToUtf16(*n) == c)
|
||||
return n - b;
|
||||
} else {
|
||||
c = foldCase(c);
|
||||
for (; n >= b; --n)
|
||||
if (foldCase(valueTypeToUtf16(*n)) == c)
|
||||
return n - b;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<typename Haystack, typename Needle>
|
||||
static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
|
||||
Needle needle0, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
const qsizetype sl = needle0.size();
|
||||
if (sl == 1)
|
||||
return qLastIndexOf(haystack0, needle0.front(), from, cs);
|
||||
|
||||
const qsizetype l = haystack0.size();
|
||||
if (from < 0)
|
||||
from += l;
|
||||
if (from == l && sl == 0)
|
||||
return from;
|
||||
const qsizetype delta = l - sl;
|
||||
if (std::size_t(from) >= std::size_t(l) || delta < 0)
|
||||
return -1;
|
||||
if (from > delta)
|
||||
from = delta;
|
||||
|
||||
auto sv = [sl](const typename Haystack::value_type *v) { return Haystack(v, sl); };
|
||||
|
||||
auto haystack = haystack0.data();
|
||||
const auto needle = needle0.data();
|
||||
const auto *end = haystack;
|
||||
haystack += from;
|
||||
const std::size_t sl_minus_1 = sl - 1;
|
||||
const auto *n = needle + sl_minus_1;
|
||||
const auto *h = haystack + sl_minus_1;
|
||||
std::size_t hashNeedle = 0, hashHaystack = 0;
|
||||
qsizetype idx;
|
||||
|
||||
if (cs == Qt::CaseSensitive) {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = (hashNeedle << 1) + valueTypeToUtf16(*(n - idx));
|
||||
hashHaystack = (hashHaystack << 1) + valueTypeToUtf16(*(h - idx));
|
||||
}
|
||||
hashHaystack -= valueTypeToUtf16(*haystack);
|
||||
|
||||
while (haystack >= end) {
|
||||
hashHaystack += valueTypeToUtf16(*haystack);
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
|
||||
return haystack - end;
|
||||
--haystack;
|
||||
REHASH(valueTypeToUtf16(haystack[sl]));
|
||||
}
|
||||
} else {
|
||||
for (idx = 0; idx < sl; ++idx) {
|
||||
hashNeedle = (hashNeedle << 1) + foldCaseHelper(n - idx, needle);
|
||||
hashHaystack = (hashHaystack << 1) + foldCaseHelper(h - idx, end);
|
||||
}
|
||||
hashHaystack -= foldCaseHelper(haystack, end);
|
||||
|
||||
while (haystack >= end) {
|
||||
hashHaystack += foldCaseHelper(haystack, end);
|
||||
if (hashHaystack == hashNeedle
|
||||
&& qt_compare_strings(sv(haystack), needle0, Qt::CaseInsensitive) == 0)
|
||||
return haystack - end;
|
||||
--haystack;
|
||||
REHASH(foldCaseHelper(haystack + sl, end));
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
if (haystack.size() < needle.size())
|
||||
@ -11961,6 +12031,26 @@ qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QLatin1S
|
||||
QStringView(reinterpret_cast<const QChar*>(n.constData()), n.size()), cs);
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
return qLastIndexOf(haystack, from, needle, cs);
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
return qLastIndexOf(haystack, from, needle, cs);
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
return qLastIndexOf(haystack, from, needle, cs);
|
||||
}
|
||||
|
||||
qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
|
||||
{
|
||||
return qLastIndexOf(haystack, from, needle, cs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.8
|
||||
|
||||
|
@ -145,6 +145,13 @@ public:
|
||||
Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return indexOf(QStringView(&c, 1), 0, cs) != -1; }
|
||||
|
||||
Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
Q_REQUIRED_RESULT int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
Q_REQUIRED_RESULT inline int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize
|
||||
|
||||
using value_type = const char;
|
||||
using reference = value_type&;
|
||||
using const_reference = reference;
|
||||
@ -235,6 +242,8 @@ qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitiv
|
||||
{ return QtPrivate::findString(*this, from, s, cs); }
|
||||
bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
|
||||
{ return indexOf(s, 0, cs) != qsizetype(-1); }
|
||||
qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
|
||||
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
|
||||
|
||||
class Q_CORE_EXPORT QString
|
||||
{
|
||||
@ -357,9 +366,14 @@ public:
|
||||
Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
#endif
|
||||
|
||||
Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
|
||||
inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
@ -1541,10 +1555,14 @@ public:
|
||||
{ return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
#endif
|
||||
int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
|
||||
|
||||
#if QT_STRINGVIEW_LEVEL < 2
|
||||
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||
|
@ -80,6 +80,11 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStrin
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
|
||||
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) noexcept;
|
||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) noexcept;
|
||||
|
||||
|
@ -754,6 +754,24 @@ QT_BEGIN_NAMESPACE
|
||||
\sa indexOf()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn qsizetype QStringView::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
|
||||
\fn qsizetype QStringView::lastIndexOf(QLatin1String l1, qsizetype from, Qt::CaseSensitivity cs) const
|
||||
\fn qsizetype QStringView::lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const
|
||||
\since 5.14
|
||||
|
||||
Returns the index position of the last occurrence of the string-view \a str,
|
||||
Latin-1 string \a l1, or character \a ch, respectively, in this string-view,
|
||||
searching backward from index position \a from. If \a from is -1 (default),
|
||||
the search starts at the last character; if \a from is -2, at the next to last
|
||||
character and so on. Returns -1 if \a str is not found.
|
||||
|
||||
If \a cs is Qt::CaseSensitive (default), the search is case
|
||||
sensitive; otherwise the search is case insensitive.
|
||||
|
||||
\sa QString::lastIndexOf()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QByteArray QStringView::toLatin1() const
|
||||
|
||||
|
@ -282,6 +282,12 @@ public:
|
||||
{ return indexOf(s, 0, cs) != qsizetype(-1); }
|
||||
Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
|
||||
|
||||
Q_REQUIRED_RESULT qsizetype lastIndexOf(QChar c, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
|
||||
Q_REQUIRED_RESULT qsizetype lastIndexOf(QStringView s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
|
||||
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
|
||||
Q_REQUIRED_RESULT inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
|
||||
|
||||
Q_REQUIRED_RESULT bool isRightToLeft() const noexcept
|
||||
{ return QtPrivate::isRightToLeft(*this); }
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
|
||||
** Copyright (C) 2019 Mail.ru Group.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
@ -526,6 +527,47 @@ private Q_SLOTS:
|
||||
void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); }
|
||||
void contains_QStringView_QStringView_data() { contains_data(); }
|
||||
void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); }
|
||||
|
||||
private:
|
||||
template <typename Haystack, typename Needle> void lastIndexOf_impl() const;
|
||||
void lastIndexOf_data();
|
||||
|
||||
private Q_SLOTS:
|
||||
void lastIndexOf_QString_QString_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); }
|
||||
void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QString_QLatin1String() { lastIndexOf_impl<QString, QLatin1String>(); }
|
||||
void lastIndexOf_QString_QStringRef_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); }
|
||||
void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); }
|
||||
|
||||
void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); }
|
||||
void lastIndexOf_QLatin1String_QLatin1String_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QLatin1String_QLatin1String() { lastIndexOf_impl<QLatin1String, QLatin1String>(); }
|
||||
void lastIndexOf_QLatin1String_QStringRef_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); }
|
||||
void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); }
|
||||
|
||||
void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); }
|
||||
void lastIndexOf_QStringRef_QLatin1String_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringRef_QLatin1String() { lastIndexOf_impl<QStringRef, QLatin1String>(); }
|
||||
void lastIndexOf_QStringRef_QStringRef_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); }
|
||||
void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); }
|
||||
|
||||
void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); }
|
||||
void lastIndexOf_QStringView_QLatin1String_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringView_QLatin1String() { lastIndexOf_impl<QStringView, QLatin1String>(); }
|
||||
void lastIndexOf_QStringView_QStringRef_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); }
|
||||
void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); }
|
||||
void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); }
|
||||
};
|
||||
|
||||
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
|
||||
@ -1626,6 +1668,118 @@ void tst_QStringApiSymmetry::contains_impl() const
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QStringApiSymmetry::lastIndexOf_data()
|
||||
{
|
||||
QTest::addColumn<QString>("haystackU16");
|
||||
QTest::addColumn<QLatin1String>("haystackL1");
|
||||
QTest::addColumn<QString>("needleU16");
|
||||
QTest::addColumn<QLatin1String>("needleL1");
|
||||
QTest::addColumn<qsizetype>("startpos");
|
||||
QTest::addColumn<qsizetype>("resultCS");
|
||||
QTest::addColumn<qsizetype>("resultCIS");
|
||||
|
||||
constexpr qsizetype zeroPos = 0;
|
||||
constexpr qsizetype minus1Pos = -1;
|
||||
|
||||
QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
|
||||
<< null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
|
||||
<< null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
|
||||
<< null << QLatin1String() << minus1Pos << zeroPos << zeroPos;
|
||||
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
|
||||
<< empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
|
||||
<< empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos;
|
||||
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
|
||||
<< empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
|
||||
<< a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
|
||||
<< a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
|
||||
|
||||
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
|
||||
<< null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1);
|
||||
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
|
||||
<< empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1);
|
||||
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
|
||||
<< null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos;
|
||||
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
|
||||
<< empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos;
|
||||
|
||||
#define ROW(h, n, st, cs, cis) \
|
||||
QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
|
||||
<< n << QLatin1String(#n) \
|
||||
<< qsizetype(st) << qsizetype(cs) << qsizetype(cis)
|
||||
|
||||
ROW(asd, asdf, -1, -1, -1);
|
||||
|
||||
ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14);
|
||||
ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14);
|
||||
ROW(ABCDEFGHIEfGEFG, G, -3, 11, 11);
|
||||
ROW(ABCDEFGHIEfGEFG, g, -3, -1, 11);
|
||||
ROW(ABCDEFGHIEfGEFG, G, -5, 6, 6);
|
||||
ROW(ABCDEFGHIEfGEFG, g, -5, -1, 6);
|
||||
ROW(ABCDEFGHIEfGEFG, G, 14, 14, 14);
|
||||
ROW(ABCDEFGHIEfGEFG, g, 14, -1, 14);
|
||||
ROW(ABCDEFGHIEfGEFG, G, 13, 11, 11);
|
||||
ROW(ABCDEFGHIEfGEFG, g, 13, -1, 11);
|
||||
ROW(ABCDEFGHIEfGEFG, G, 15, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, g, 15, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, B, 14, 1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, b, 14, -1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, B, -1, 1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, b, -1, -1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, B, 1, 1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, b, 1, -1, 1);
|
||||
ROW(ABCDEFGHIEfGEFG, B, 0, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, b, 0, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, A, 0, 0, 0);
|
||||
ROW(ABCDEFGHIEfGEFG, a, 0, -1, 0);
|
||||
ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0);
|
||||
ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0);
|
||||
|
||||
ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
|
||||
ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
|
||||
#undef ROW
|
||||
}
|
||||
|
||||
template <typename Haystack, typename Needle>
|
||||
void tst_QStringApiSymmetry::lastIndexOf_impl() const
|
||||
{
|
||||
QFETCH(const QString, haystackU16);
|
||||
QFETCH(const QLatin1String, haystackL1);
|
||||
QFETCH(const QString, needleU16);
|
||||
QFETCH(const QLatin1String, needleL1);
|
||||
QFETCH(const qsizetype, startpos);
|
||||
QFETCH(const qsizetype, resultCS);
|
||||
QFETCH(const qsizetype, resultCIS);
|
||||
|
||||
const auto haystackU8 = haystackU16.toUtf8();
|
||||
const auto needleU8 = needleU16.toUtf8();
|
||||
|
||||
const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
|
||||
const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
|
||||
|
||||
using size_type = typename Haystack::size_type;
|
||||
|
||||
QCOMPARE(haystack.lastIndexOf(needle, startpos), size_type(resultCS));
|
||||
QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
|
||||
QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
|
||||
|
||||
if (needle.size() == 1)
|
||||
{
|
||||
QCOMPARE(haystack.lastIndexOf(needle[0], startpos), size_type(resultCS));
|
||||
QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
|
||||
QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)
|
||||
|
||||
#include "tst_qstringapisymmetry.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user