QString: reorganize some template functions

This is going to screw up the git blame functionality (which is why they
were forward-declared instead of implemented on-site) but the
alternative is that Qt Creator thinks qstring.cpp had almost no
functions inside.

Pick-to: 6.3 6.2
Task-number: QTCREATORBUG-25594
Change-Id: Ib42b3adc93bf4d43bd55fffd16c1986f1a3c1574
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira 2021-12-17 13:42:22 -03:00
parent d0908d0095
commit 1ed19dc018

View File

@ -102,11 +102,196 @@
#endif
#define IS_RAW_DATA(d) ((d.d)->flags & QArrayData::RawDataType)
#define REHASH(a) \
if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
hashHaystack -= std::size_t(a) << sl_minus_1; \
hashHaystack <<= 1
QT_BEGIN_NAMESPACE
const char16_t QString::_empty = 0;
// in qstringmatcher.cpp
qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
namespace {
inline bool qIsUpper(char ch)
{
return ch >= 'A' && ch <= 'Z';
}
inline bool qIsDigit(char ch)
{
return ch >= '0' && ch <= '9';
}
inline char qToLower(char ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch - 'A' + 'a';
else
return ch;
}
template <typename Pointer>
char32_t foldCaseHelper(Pointer ch, Pointer start) = delete;
template <>
char32_t foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
{
return foldCase(reinterpret_cast<const char16_t*>(ch),
reinterpret_cast<const char16_t*>(start));
}
template <>
char32_t foldCaseHelper<const char*>(const char* ch, const char*)
{
return foldCase(char16_t(uchar(*ch)));
}
template <typename T>
char16_t valueTypeToUtf16(T t) = delete;
template <>
char16_t valueTypeToUtf16<QChar>(QChar t)
{
return t.unicode();
}
template <>
char16_t valueTypeToUtf16<char>(char t)
{
return char16_t{uchar(t)};
}
/*!
\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 inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept
{
if (-from > str.size())
return -1;
if (from < 0)
from = qMax(from + str.size(), qsizetype(0));
if (from < str.size()) {
const char16_t *s = str.utf16();
char16_t c = ch.unicode();
const char16_t *n = s + from;
const char16_t *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;
}
template <typename Haystack>
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
qsizetype from, Qt::CaseSensitivity cs) noexcept
{
if (haystack.size() == 0)
return -1;
if (from < 0)
from += haystack.size();
else if (std::size_t(from) > std::size_t(haystack.size()))
from = haystack.size() - 1;
if (from >= 0) {
char16_t 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 <> qsizetype
qLastIndexOf(QString, QChar, qsizetype, Qt::CaseSensitivity) noexcept = delete; // unwanted, would detach
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 ? sl - 1 : 0;
const auto *n = needle + sl_minus_1;
const auto *h = haystack + sl_minus_1;
std::size_t hashNeedle = 0, hashHaystack = 0;
if (cs == Qt::CaseSensitive) {
for (qsizetype 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
&& QtPrivate::compareStrings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
return haystack - end;
--haystack;
REHASH(valueTypeToUtf16(haystack[sl]));
}
} else {
for (qsizetype 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
&& QtPrivate::compareStrings(sv(haystack), needle0, Qt::CaseInsensitive) == 0)
return haystack - end;
--haystack;
REHASH(foldCaseHelper(haystack + sl, end));
}
}
return -1;
}
} // unnamed namespace
/*
* Note on the use of SIMD in qstring.cpp:
*
@ -144,15 +329,6 @@ extern "C" void qt_fromlatin1_mips_asm_unroll8 (char16_t*, const char*, uint);
extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const char16_t *src, int length);
#endif
// 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;
template <typename Haystack>
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
template <>
inline qsizetype qLastIndexOf(QString haystack, QChar needle,
qsizetype from, Qt::CaseSensitivity cs) noexcept = delete; // unwanted, would detach
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);
@ -1466,29 +1642,6 @@ int QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSens
});
}
#define REHASH(a) \
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)
{
return ch >= 'A' && ch <= 'Z';
}
inline bool qIsDigit(char ch)
{
return ch >= '0' && ch <= '9';
}
inline char qToLower(char ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch - 'A' + 'a';
else
return ch;
}
// ### Qt 7: do not allow anything but ASCII digits
// in arg()'s replacements.
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
@ -10292,74 +10445,6 @@ bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseS
return qt_ends_with_impl(haystack, needle, cs);
}
namespace {
template <typename Pointer>
char32_t foldCaseHelper(Pointer ch, Pointer start) = delete;
template <>
char32_t foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
{
return foldCase(reinterpret_cast<const char16_t*>(ch),
reinterpret_cast<const char16_t*>(start));
}
template <>
char32_t foldCaseHelper<const char*>(const char* ch, const char*)
{
return foldCase(char16_t(uchar(*ch)));
}
template <typename T>
char16_t valueTypeToUtf16(T t) = delete;
template <>
char16_t valueTypeToUtf16<QChar>(QChar t)
{
return t.unicode();
}
template <>
char16_t valueTypeToUtf16<char>(char t)
{
return char16_t{uchar(t)};
}
}
/*!
\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 inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept
{
if (-from > str.size())
return -1;
if (from < 0)
from = qMax(from + str.size(), qsizetype(0));
if (from < str.size()) {
const char16_t *s = str.utf16();
char16_t c = ch.unicode();
const char16_t *n = s + from;
const char16_t *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) noexcept
{
const qsizetype l = haystack0.size();
@ -10435,98 +10520,6 @@ 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 (haystack.size() == 0)
return -1;
if (from < 0)
from += haystack.size();
else if (std::size_t(from) > std::size_t(haystack.size()))
from = haystack.size() - 1;
if (from >= 0) {
char16_t 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 ? sl - 1 : 0;
const auto *n = needle + sl_minus_1;
const auto *h = haystack + sl_minus_1;
std::size_t hashNeedle = 0, hashHaystack = 0;
if (cs == Qt::CaseSensitive) {
for (qsizetype 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
&& QtPrivate::compareStrings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
return haystack - end;
--haystack;
REHASH(valueTypeToUtf16(haystack[sl]));
}
} else {
for (qsizetype 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
&& QtPrivate::compareStrings(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())