From b4ead572501179244aa036e7a590fa7536929f2b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 14 May 2019 15:04:18 +0200 Subject: Move away from using 0 as a pointer constant Cleans up most of corelib to use nullptr or default enums where appropriate. Change-Id: Ifcaac14ecdaaee730f87f10941db3ce407d71ef9 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 963c2a4d34..345a786df4 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3044,7 +3044,7 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar { // Copy after if it lies inside our own d->data() area (which we could // possibly invalidate via a realloc or modify by replacement). - QChar *afterBuffer = 0; + QChar *afterBuffer = nullptr; if (pointsIntoRange(after, d->data(), d->size)) // Use copy in place of vulnerable original: after = afterBuffer = textCopy(after, alen); @@ -3129,7 +3129,7 @@ QString &QString::replace(const QChar *before, int blen, return *this; QStringMatcher matcher(before, blen, cs); - QChar *beforeBuffer = 0, *afterBuffer = 0; + QChar *beforeBuffer = nullptr, *afterBuffer = nullptr; int index = 0; while (1) { @@ -5591,7 +5591,7 @@ QString QString::fromUtf16(const ushort *unicode, int size) while (unicode[size] != 0) ++size; } - return QUtf16::convertToUnicode((const char *)unicode, size*2, 0); + return QUtf16::convertToUnicode((const char *)unicode, size*2, nullptr); } /*! @@ -5645,7 +5645,7 @@ QString QString::fromUcs4(const uint *unicode, int size) while (unicode[size] != 0) ++size; } - return QUtf32::convertToUnicode((const char *)unicode, size*4, 0); + return QUtf32::convertToUnicode((const char *)unicode, size*4, nullptr); } @@ -8060,7 +8060,7 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar:: version = QChar::currentUnicodeVersion(); } else if (int(version) <= NormalizationCorrectionsVersionMax) { const QString &s = *data; - QChar *d = 0; + QChar *d = nullptr; for (int i = 0; i < NumNormalizationCorrections; ++i) { const NormalizationCorrection &n = uc_normalization_corrections[i]; if (n.version > version) { -- cgit v1.2.3 From 54bf20af5dca8ccd835344fd46a9c4c1ee7b8c61 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jun 2019 11:43:24 +0200 Subject: QString: towards QStringView::arg() pt.1: modernize some code Replace explicit iterator loops with ranged for loops. Also remove the pointless detach() of the QString result, caused by calling mutable data() instead of using the old trick of const-casting constData(). Change-Id: Ia7e2cb2926dc30b4dba33200b17697fd33d22446 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 345a786df4..c5a98c9f22 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8915,9 +8915,9 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult & { ArgIndexToPlaceholderMap result; - for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { - if (it->number >= 0) - result.push_back(it->number); + for (Part part : parts) { + if (part.number >= 0) + result.push_back(part.number); } std::sort(result.begin(), result.end()); @@ -8930,14 +8930,13 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult & static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) { int totalSize = 0; - for (ParseResult::iterator pit = parts.begin(), end = parts.end(); pit != end; ++pit) { - if (pit->number != -1) { - const ArgIndexToPlaceholderMap::const_iterator ait - = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), pit->number); - if (ait != argIndexToPlaceholderMap.end()) - pit->stringRef = QStringRef(args[ait - argIndexToPlaceholderMap.begin()]); + for (Part &part : parts) { + if (part.number != -1) { + const auto it = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), part.number); + if (it != argIndexToPlaceholderMap.end()) + part.stringRef = QStringRef(args[it - argIndexToPlaceholderMap.begin()]); } - totalSize += pit->stringRef.size(); + totalSize += part.stringRef.size(); } return totalSize; } @@ -8963,11 +8962,11 @@ QString QString::multiArg(int numArgs, const QString **args) const // 6: QString result(totalSize, Qt::Uninitialized); - QChar *out = result.data(); + auto out = const_cast(result.constData()); - for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) { - if (const int sz = it->stringRef.size()) { - memcpy(out, it->stringRef.constData(), sz * sizeof(QChar)); + for (Part part : parts) { + if (const int sz = part.stringRef.size()) { + memcpy(out, part.stringRef.data(), sz * sizeof(QChar)); out += sz; } } -- cgit v1.2.3 From a44a3a4999329b054c575e9600a556454cf6111d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jun 2019 11:43:24 +0200 Subject: QString: towards QStringView::arg() pt.2: port internal machinery to QStringView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This involves replacing the use of QStringRef with QStringView and replacing int indexes and sizes with qsizetype ones. Since we use QStringView now, where mid() is cheap and well-defined, remove the offset and length parameters that used to be Part ctor arguments, and use mid() in the caller. Change-Id: I08f3cd467b7b935f734b73d15eb8564b7deaa87e Reviewed-by: Edward Welbourne Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c5a98c9f22..2d4f10ecb0 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8797,7 +8797,7 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar); } -static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999) +static int getEscape(const QChar *uc, qsizetype *pos, qsizetype len, int maxNumber = 999) { int i = *pos; ++i; @@ -8860,17 +8860,17 @@ static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999) namespace { struct Part { - Part() : stringRef(), number(0) {} - Part(const QString &s, int pos, int len, int num = -1) noexcept - : stringRef(&s, pos, len), number(num) {} + Q_DECL_CONSTEXPR Part() : string{}, number{0} {} + Q_DECL_CONSTEXPR Part(QStringView s, int num = -1) + : string{s}, number{num} {} - QStringRef stringRef; + QStringView string; int number; }; } // unnamed namespace template <> -class QTypeInfo : public QTypeInfoMerger {}; // Q_DECLARE_METATYPE +class QTypeInfo : public QTypeInfoMerger {}; // Q_DECLARE_METATYPE namespace { @@ -8880,24 +8880,24 @@ enum { ExpectedParts = 32 }; typedef QVarLengthArray ParseResult; typedef QVarLengthArray ArgIndexToPlaceholderMap; -static ParseResult parseMultiArgFormatString(const QString &s) +static ParseResult parseMultiArgFormatString(QStringView s) { ParseResult result; - const QChar *uc = s.constData(); - const int len = s.size(); - const int end = len - 1; - int i = 0; - int last = 0; + const auto uc = s.data(); + const auto len = s.size(); + const auto end = len - 1; + qsizetype i = 0; + qsizetype last = 0; while (i < end) { if (uc[i] == QLatin1Char('%')) { - int percent = i; + qsizetype percent = i; int number = getEscape(uc, &i, len); if (number != -1) { if (last != percent) - result.push_back(Part(s, last, percent - last)); // literal text (incl. failed placeholders) - result.push_back(Part(s, percent, i - percent, number)); // parsed placeholder + result.push_back(Part{s.mid(last, percent - last)}); // literal text (incl. failed placeholders) + result.push_back(Part{s.mid(percent, i - percent), number}); // parsed placeholder last = i; continue; } @@ -8906,7 +8906,7 @@ static ParseResult parseMultiArgFormatString(const QString &s) } if (last < len) - result.push_back(Part(s, last, len - last)); // trailing literal text + result.push_back(Part{s.mid(last, len - last)}); // trailing literal text return result; } @@ -8927,16 +8927,16 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult & return result; } -static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) +static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) { - int totalSize = 0; + qsizetype totalSize = 0; for (Part &part : parts) { if (part.number != -1) { const auto it = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), part.number); if (it != argIndexToPlaceholderMap.end()) - part.stringRef = QStringRef(args[it - argIndexToPlaceholderMap.begin()]); + part.string = *args[it - argIndexToPlaceholderMap.begin()]; } - totalSize += part.stringRef.size(); + totalSize += part.string.size(); } return totalSize; } @@ -8946,7 +8946,7 @@ static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgInde QString QString::multiArg(int numArgs, const QString **args) const { // Step 1-2 above - ParseResult parts = parseMultiArgFormatString(*this); + ParseResult parts = parseMultiArgFormatString(qToStringViewIgnoringNull(*this)); // 3-4 ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts); @@ -8958,15 +8958,15 @@ QString QString::multiArg(int numArgs, const QString **args) const numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data()); // 5 - const int totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args); + const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args); // 6: QString result(totalSize, Qt::Uninitialized); auto out = const_cast(result.constData()); for (Part part : parts) { - if (const int sz = part.stringRef.size()) { - memcpy(out, part.stringRef.data(), sz * sizeof(QChar)); + if (const qsizetype sz = part.string.size()) { + memcpy(out, part.string.data(), sz * sizeof(QChar)); out += sz; } } -- cgit v1.2.3 From 55240bcdf3cc1d6ac357e5007748378c6bf1d7f1 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Tue, 2 Apr 2019 16:24:44 +0300 Subject: 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 --- src/corelib/tools/qstring.cpp | 340 ++++++++++++++++++++++++++---------------- 1 file changed, 215 insertions(+), 125 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 2d4f10ecb0..53513d4abb 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -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 +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(haystack.unicode()), from, - reinterpret_cast(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 s(size); - qt_from_latin1(s.data(), needle.latin1(), size); - return lastIndexOfHelper(reinterpret_cast(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 -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(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 +uint foldCaseHelper(Pointer ch, Pointer start) = delete; + +template <> +uint foldCaseHelper(const QChar* ch, const QChar* start) +{ + return foldCase(reinterpret_cast(ch), reinterpret_cast(start)); +} + +template <> +uint foldCaseHelper(const char* ch, const char*) +{ + return foldCase(ushort(uchar(*ch))); +} + +template +ushort valueTypeToUtf16(T t) = delete; + +template <> +ushort valueTypeToUtf16(QChar t) +{ + return t.unicode(); +} + +template <> +ushort valueTypeToUtf16(char t) +{ + return ushort(uchar(t)); +} +} + /*! \internal @@ -11928,6 +11907,97 @@ 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 (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 +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(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 -- cgit v1.2.3 From 35431062bd7bf0d27b9bf785ab3cbc7fac5a69da Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jun 2019 11:43:24 +0200 Subject: QString: towards QStringView::arg() pt.3: Long live QStringView/QLatin1String::arg() This version of arg(), unlike its QString counterpart, transparently accepts views without conversion to QString, and is also extensible to further argument types, say a future QFormattedNumber. [ChangeLog][QtCore][QStringView/QLatin1String] Added arg(), taking arbitrarily many strings. Change-Id: If40ef3c445f63383e32573f3f515fdda84c7fe3a Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 108 +++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 23 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 53513d4abb..89ab866703 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8754,19 +8754,23 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar); } -static int getEscape(const QChar *uc, qsizetype *pos, qsizetype len, int maxNumber = 999) +static inline ushort to_unicode(const QChar c) { return c.unicode(); } +static inline ushort to_unicode(const char c) { return QLatin1Char{c}.unicode(); } + +template +static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999) { int i = *pos; ++i; if (i < len && uc[i] == QLatin1Char('L')) ++i; if (i < len) { - int escape = uc[i].unicode() - '0'; + int escape = to_unicode(uc[i]) - '0'; if (uint(escape) >= 10U) return -1; ++i; while (i < len) { - int digit = uc[i].unicode() - '0'; + int digit = to_unicode(uc[i]) - '0'; if (uint(digit) >= 10U) break; escape = (escape * 10) + digit; @@ -8817,18 +8821,23 @@ static int getEscape(const QChar *uc, qsizetype *pos, qsizetype len, int maxNumb namespace { struct Part { - Q_DECL_CONSTEXPR Part() : string{}, number{0} {} + Part() = default; // for QVarLengthArray; do not use Q_DECL_CONSTEXPR Part(QStringView s, int num = -1) - : string{s}, number{num} {} + : tag{QtPrivate::ArgBase::U16}, number{num}, data{s.utf16()}, size{s.size()} {} + Q_DECL_CONSTEXPR Part(QLatin1String s, int num = -1) + : tag{QtPrivate::ArgBase::L1}, number{num}, data{s.data()}, size{s.size()} {} + + void reset(QStringView s) noexcept { *this = {s, number}; } + void reset(QLatin1String s) noexcept { *this = {s, number}; } - QStringView string; + QtPrivate::ArgBase::Tag tag; int number; + const void *data; + qsizetype size; }; } // unnamed namespace -template <> -class QTypeInfo : public QTypeInfoMerger {}; // Q_DECLARE_METATYPE - +Q_DECLARE_TYPEINFO(Part, Q_PRIMITIVE_TYPE); namespace { @@ -8837,7 +8846,8 @@ enum { ExpectedParts = 32 }; typedef QVarLengthArray ParseResult; typedef QVarLengthArray ArgIndexToPlaceholderMap; -static ParseResult parseMultiArgFormatString(QStringView s) +template +static ParseResult parseMultiArgFormatString(StringView s) { ParseResult result; @@ -8884,16 +8894,29 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult & return result; } -static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[]) +static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QtPrivate::ArgBase *args[]) { + using namespace QtPrivate; qsizetype totalSize = 0; for (Part &part : parts) { if (part.number != -1) { const auto it = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), part.number); - if (it != argIndexToPlaceholderMap.end()) - part.string = *args[it - argIndexToPlaceholderMap.begin()]; + if (it != argIndexToPlaceholderMap.end()) { + const auto &arg = *args[it - argIndexToPlaceholderMap.begin()]; + switch (arg.tag) { + case ArgBase::L1: + part.reset(static_cast(arg).string); + break; + case ArgBase::U8: + Q_UNREACHABLE(); // waiting for QUtf8String... + break; + case ArgBase::U16: + part.reset(static_cast(arg).string); + break; + } + } } - totalSize += part.string.size(); + totalSize += part.size; } return totalSize; } @@ -8901,18 +8924,35 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A } // unnamed namespace QString QString::multiArg(int numArgs, const QString **args) const +{ + QVarLengthArray sva; + sva.reserve(numArgs); + QVarLengthArray pointers; + pointers.reserve(numArgs); + for (int i = 0; i < numArgs; ++i) { + sva.push_back(QtPrivate::qStringLikeToArg(*args[i])); + pointers.push_back(&sva.back()); + } + return QtPrivate::argToQString(qToStringViewIgnoringNull(*this), static_cast(numArgs), pointers.data()); +} + +Q_ALWAYS_INLINE QString to_string(QLatin1String s) noexcept { return s; } +Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); } + +template +static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPrivate::ArgBase **args) { // Step 1-2 above - ParseResult parts = parseMultiArgFormatString(qToStringViewIgnoringNull(*this)); + ParseResult parts = parseMultiArgFormatString(pattern); // 3-4 ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts); - if (argIndexToPlaceholderMap.size() > numArgs) // 3a - argIndexToPlaceholderMap.resize(numArgs); - else if (argIndexToPlaceholderMap.size() < numArgs) // 3b - qWarning("QString::arg: %d argument(s) missing in %s", - numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data()); + if (static_cast(argIndexToPlaceholderMap.size()) > numArgs) // 3a + argIndexToPlaceholderMap.resize(int(numArgs)); + else if (Q_UNLIKELY(static_cast(argIndexToPlaceholderMap.size()) < numArgs)) // 3b + qWarning("QString::arg: %d argument(s) missing in %ls", + int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(to_string(pattern))); // 5 const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args); @@ -8922,15 +8962,37 @@ QString QString::multiArg(int numArgs, const QString **args) const auto out = const_cast(result.constData()); for (Part part : parts) { - if (const qsizetype sz = part.string.size()) { - memcpy(out, part.string.data(), sz * sizeof(QChar)); - out += sz; + switch (part.tag) { + case QtPrivate::ArgBase::L1: + if (part.size) { + qt_from_latin1(reinterpret_cast(out), + reinterpret_cast(part.data), part.size); + } + break; + case QtPrivate::ArgBase::U8: + Q_UNREACHABLE(); // waiting for QUtf8String + break; + case QtPrivate::ArgBase::U16: + if (part.size) + memcpy(out, part.data, part.size * sizeof(QChar)); + break; } + out += part.size; } return result; } +QString QtPrivate::argToQString(QStringView pattern, size_t n, const ArgBase **args) +{ + return argToQStringImpl(pattern, n, args); +} + +QString QtPrivate::argToQString(QLatin1String pattern, size_t n, const ArgBase **args) +{ + return argToQStringImpl(pattern, n, args); +} + /*! \fn bool QString::isSimpleText() const \internal -- cgit v1.2.3 From 7000b70821493222ea2af10aae420b8cdd830953 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jun 2019 11:43:24 +0200 Subject: QString: towards QStringView::arg() pt.4: port QString::arg() to QStringView::arg() This allows us to drop QString::multiArg() from the build as soon as we can break BC, ie. in Qt 6. Change-Id: Ibdfbf9e9586952e0ec125120bb5966eb56c0ce67 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 89ab866703..f9a9fcfe91 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8923,6 +8923,7 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A } // unnamed namespace +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QString QString::multiArg(int numArgs, const QString **args) const { QVarLengthArray sva; @@ -8935,6 +8936,7 @@ QString QString::multiArg(int numArgs, const QString **args) const } return QtPrivate::argToQString(qToStringViewIgnoringNull(*this), static_cast(numArgs), pointers.data()); } +#endif Q_ALWAYS_INLINE QString to_string(QLatin1String s) noexcept { return s; } Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); } -- cgit v1.2.3 From fc940b24dbe8a118e92e335c0d9c7d4194bf3d4f Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Tue, 18 Jun 2019 17:19:08 +0300 Subject: QString: fix comments for qsizetype Change-Id: I445ba61513fbafd24834fa48ade849feae4f1324 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index f9a9fcfe91..319f82af53 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3701,7 +3701,7 @@ bool QString::operator>(QLatin1String other) const noexcept */ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } #endif // QT_STRINGVIEW_LEVEL < 2 @@ -3745,7 +3745,7 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs)); } @@ -3758,7 +3758,7 @@ int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const */ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qFindChar(QStringView(unicode(), length()), ch, from, cs)); } @@ -3777,7 +3777,7 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } @@ -3799,7 +3799,7 @@ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) co */ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } @@ -3826,7 +3826,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c */ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } @@ -3838,7 +3838,7 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co */ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qLastIndexOf(*this, ch, from, cs)); } @@ -3860,7 +3860,7 @@ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } #endif // QT_STRINGVIEW_LEVEL < 2 @@ -4192,7 +4192,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) int QString::count(const QString &str, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } @@ -4209,7 +4209,7 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const int QString::count(QChar ch, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), ch, cs)); } @@ -4226,7 +4226,7 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const */ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } @@ -11172,7 +11172,7 @@ QStringRef QString::midRef(int position, int n) const */ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs)); } #endif // QT_STRINGVIEW_LEVEL < 2 @@ -11207,7 +11207,7 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co */ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qFindChar(QStringView(unicode(), length()), ch, from, cs)); } @@ -11228,7 +11228,7 @@ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs)); } @@ -11249,7 +11249,7 @@ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) con */ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs)); } #endif // QT_STRINGVIEW_LEVEL < 2 @@ -11270,7 +11270,7 @@ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) */ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } @@ -11285,7 +11285,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 + // ### Qt6: qsizetype return int(qLastIndexOf(*this, ch, from, cs)); } @@ -11306,7 +11306,7 @@ int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } @@ -11327,7 +11327,7 @@ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) */ int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(QtPrivate::lastIndexOf(*this, from, str, cs)); } @@ -11360,7 +11360,7 @@ int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity */ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } @@ -11378,7 +11378,7 @@ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const */ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), ch, cs)); } @@ -11396,7 +11396,7 @@ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const */ int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const { - // ### Qt6: qsize + // ### Qt6: qsizetype return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } -- cgit v1.2.3 From b321559a22a3ee6490695ecb9d95d3c9fbf7ee1c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Apr 2019 11:13:04 -0700 Subject: Document OOM conditions in the QArrayData-based containers The other containers probably don't handle as well, so I just documented the ones that I know how they work. Fixes: QTBUG-75470 Change-Id: I95ecabe2f50e450c991afffd159a0483aac35a79 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Albert Astals Cid Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/corelib/tools/qstring.cpp') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ee9d486eb8..a0e33d4e45 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1777,6 +1777,24 @@ const QString::Null QString::null = { }; and the \c{'+'} will automatically be performed as the \c{QStringBuilder} \c{'%'} everywhere. + \section1 Maximum size and out-of-memory conditions + + The current version of QString is limited to just under 2 GB (2^31 bytes) + in size. The exact value is architecture-dependent, since it depends on the + overhead required for managing the data block, but is no more than 32 + bytes. Raw data blocks are also limited by the use of \c int type in the + current version to 2 GB minus 1 byte. Since QString uses two bytes per + character, that translates to just under 2^30 characters in one QString. + + In case memory allocation fails, QString will throw a \c std::bad_alloc + exception. Out of memory conditions in the Qt containers are the only case + where Qt will throw exceptions. + + Note that the operating system may impose further limits on applications + holding a lot of allocated memory, especially large, contiguous blocks. + Such considerations, the configuration of such behavior or any mitigation + are outside the scope of the Qt API. + \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef */ -- cgit v1.2.3