From 1ed19dc01808a0abf41dffb023c4f573894b46f4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Dec 2021 13:42:22 -0300 Subject: [PATCH] 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 --- src/corelib/text/qstring.cpp | 377 +++++++++++++++++------------------ 1 file changed, 185 insertions(+), 192 deletions(-) diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 7f844db04ff..28027b158a7 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -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 +char32_t foldCaseHelper(Pointer ch, Pointer start) = delete; + +template <> +char32_t foldCaseHelper(const QChar* ch, const QChar* start) +{ + return foldCase(reinterpret_cast(ch), + reinterpret_cast(start)); +} + +template <> +char32_t foldCaseHelper(const char* ch, const char*) +{ + return foldCase(char16_t(uchar(*ch))); +} + +template +char16_t valueTypeToUtf16(T t) = delete; + +template <> +char16_t valueTypeToUtf16(QChar t) +{ + return t.unicode(); +} + +template <> +char16_t valueTypeToUtf16(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 +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 +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 -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 -char32_t foldCaseHelper(Pointer ch, Pointer start) = delete; - -template <> -char32_t foldCaseHelper(const QChar* ch, const QChar* start) -{ - return foldCase(reinterpret_cast(ch), - reinterpret_cast(start)); -} - -template <> -char32_t foldCaseHelper(const char* ch, const char*) -{ - return foldCase(char16_t(uchar(*ch))); -} - -template -char16_t valueTypeToUtf16(T t) = delete; - -template <> -char16_t valueTypeToUtf16(QChar t) -{ - return t.unicode(); -} - -template <> -char16_t valueTypeToUtf16(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 -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 -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())