summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qstring.cpp')
-rw-r--r--src/corelib/text/qstring.cpp1322
1 files changed, 843 insertions, 479 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 64ad2c537b..f0bf0c50a3 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -17,6 +17,7 @@
#include <qlist.h>
#include "qlocale.h"
#include "qlocale_p.h"
+#include "qspan.h"
#include "qstringbuilder.h"
#include "qstringmatcher.h"
#include "qvarlengtharray.h"
@@ -50,23 +51,17 @@
#ifdef Q_OS_WIN
# include <qt_windows.h>
+# if !defined(QT_BOOTSTRAPPED) && (defined(QT_NO_CAST_FROM_ASCII) || defined(QT_NO_CAST_TO_ASCII))
+// MSVC requires this, but let's apply it to MinGW compilers too, just in case
+# error "This file cannot be compiled with QT_NO_CAST_{TO,FROM}_ASCII, " \
+ "otherwise some QString functions will not get exported."
+# endif
#endif
#ifdef truncate
# undef truncate
#endif
-#ifndef LLONG_MAX
-#define LLONG_MAX qint64_C(9223372036854775807)
-#endif
-#ifndef LLONG_MIN
-#define LLONG_MIN (-LLONG_MAX - qint64_C(1))
-#endif
-#ifndef ULLONG_MAX
-#define ULLONG_MAX quint64_C(18446744073709551615)
-#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; \
@@ -133,31 +128,6 @@ static inline bool foldAndCompare(const T a, const T b)
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);
- auto it = std::find_if(n, e, [c](const auto &ch) { return foldAndCompare(ch, c); });
- if (it != e)
- return std::distance(s, it);
- }
- }
- return -1;
-}
-
template <typename Haystack>
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
qsizetype from, Qt::CaseSensitivity cs) noexcept
@@ -264,7 +234,7 @@ bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity c
if (needleLen > haystackLen)
return false;
- return QtPrivate::compareStrings(haystack.left(needleLen), needle, cs) == 0;
+ return QtPrivate::compareStrings(haystack.first(needleLen), needle, cs) == 0;
}
template <typename Haystack, typename Needle>
@@ -279,7 +249,7 @@ bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs)
if (haystackLen < needleLen)
return false;
- return QtPrivate::compareStrings(haystack.right(needleLen), needle, cs) == 0;
+ return QtPrivate::compareStrings(haystack.last(needleLen), needle, cs) == 0;
}
template <typename T>
@@ -472,7 +442,7 @@ static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
if constexpr (UseSse4_1) {
# ifndef Q_OS_QNX // compiler fails in the code below
__m128i mask;
- auto updatePtrSimd = [&](__m128i data) {
+ auto updatePtrSimd = [&](__m128i data) -> bool {
__m128i masked = _mm_and_si128(mask, data);
__m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
uint result = _mm_movemask_epi8(comparison);
@@ -684,6 +654,7 @@ static int ucstrncmp_sse2(const char16_t *a, const Char *b, size_t l)
}
#endif
+Q_NEVER_INLINE
qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
{
#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
@@ -699,6 +670,11 @@ qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
return result;
}
+qsizetype QtPrivate::qustrnlen(const char16_t *str, qsizetype maxlen) noexcept
+{
+ return qustrchr({ str, maxlen }, u'\0') - str;
+}
+
/*!
* \internal
*
@@ -707,6 +683,7 @@ qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
* character is not found, this function returns a pointer to the end of the
* string -- that is, \c{str.end()}.
*/
+Q_NEVER_INLINE
const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
{
const char16_t *n = str.utf16();
@@ -787,6 +764,23 @@ const char16_t *QtPrivate::qustrchr(QStringView str, char16_t c) noexcept
return std::find(n, e, c);
}
+/*!
+ * \internal
+ *
+ * Searches case-insensitively for character \a c in the string \a str and
+ * returns a pointer to it. Iif the character is not found, this function
+ * returns a pointer to the end of the string -- that is, \c{str.end()}.
+ */
+Q_NEVER_INLINE
+const char16_t *QtPrivate::qustrcasechr(QStringView str, char16_t c) noexcept
+{
+ const QChar *n = str.begin();
+ const QChar *e = str.end();
+ c = foldCase(c);
+ auto it = std::find_if(n, e, [c](auto ch) { return foldAndCompare(ch, QChar(c)); });
+ return reinterpret_cast<const char16_t *>(it);
+}
+
// Note: ptr on output may be off by one and point to a preceding US-ASCII
// character. Usually harmless.
bool qt_is_ascii(const char *&ptr, const char *end) noexcept
@@ -981,7 +975,7 @@ Q_CORE_EXPORT void qt_from_latin1(char16_t *dst, const char *str, size_t size) n
return;
} else {
size = size % 4;
- return UnrollTailLoop<3>::exec(qsizetype(size), [=](int i) { dst[i] = (uchar)str[i]; });
+ return UnrollTailLoop<3>::exec(qsizetype(size), [=](qsizetype i) { dst[i] = uchar(str[i]); });
}
# endif
#endif
@@ -1354,10 +1348,8 @@ static int ucstrncmp(const char16_t *a, const char *b, size_t l)
// Unicode case-sensitive equality
template <typename Char2>
-static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b, size_t blen)
+static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b)
{
- if (alen != blen)
- return false;
if constexpr (std::is_same_v<decltype(a), decltype(b)>) {
if (a == b)
return true;
@@ -1400,12 +1392,14 @@ static int latin1nicmp(const char *lhsChar, qsizetype lSize, const char *rhsChar
bool QtPrivate::equalStrings(QStringView lhs, QStringView rhs) noexcept
{
- return ucstreq(lhs.utf16(), lhs.size(), rhs.utf16(), rhs.size());
+ Q_ASSERT(lhs.size() == rhs.size());
+ return ucstreq(lhs.utf16(), lhs.size(), rhs.utf16());
}
bool QtPrivate::equalStrings(QStringView lhs, QLatin1StringView rhs) noexcept
{
- return ucstreq(lhs.utf16(), lhs.size(), rhs.latin1(), rhs.size());
+ Q_ASSERT(lhs.size() == rhs.size());
+ return ucstreq(lhs.utf16(), lhs.size(), rhs.latin1());
}
bool QtPrivate::equalStrings(QLatin1StringView lhs, QStringView rhs) noexcept
@@ -1415,7 +1409,8 @@ bool QtPrivate::equalStrings(QLatin1StringView lhs, QStringView rhs) noexcept
bool QtPrivate::equalStrings(QLatin1StringView lhs, QLatin1StringView rhs) noexcept
{
- return QByteArrayView(lhs) == QByteArrayView(rhs);
+ Q_ASSERT(lhs.size() == rhs.size());
+ return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
}
bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QStringView rhs) noexcept
@@ -1440,7 +1435,14 @@ bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QLatin1StringView
bool QtPrivate::equalStrings(QBasicUtf8StringView<false> lhs, QBasicUtf8StringView<false> rhs) noexcept
{
- return lhs.size() == rhs.size() && (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC)
+ Q_ASSERT(lhs.size() == rhs.size());
+#else
+ // operator== didn't enforce size prior to Qt 6.2
+ if (lhs.size() != rhs.size())
+ return false;
+#endif
+ return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
}
bool QAnyStringView::equal(QAnyStringView lhs, QAnyStringView rhs) noexcept
@@ -1605,7 +1607,7 @@ int QAnyStringView::compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSens
// ### Qt 7: do not allow anything but ASCII digits
// in arg()'s replacements.
-#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
static bool supportUnicodeDigitValuesInArg()
{
static const bool result = []() {
@@ -1628,7 +1630,7 @@ static bool supportUnicodeDigitValuesInArg()
static int qArgDigitValue(QChar ch) noexcept
{
-#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
if (supportUnicodeDigitValuesInArg())
return ch.digitValue();
#endif
@@ -1708,10 +1710,18 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\ingroup shared
\ingroup string-processing
+ \compares strong
+ \compareswith strong QChar QLatin1StringView {const char16_t *} \
+ QStringView QUtf8StringView
+ \endcompareswith
+ \compareswith strong QByteArray QByteArrayView {const char *}
+ When comparing with byte arrays, their content is interpreted as utf-8.
+ \endcompareswith
+
QString stores a string of 16-bit \l{QChar}s, where each QChar
corresponds to one UTF-16 code unit. (Unicode characters
with code values above 65535 are stored using surrogate pairs,
- i.e., two consecutive \l{QChar}s.)
+ that is, two consecutive \l{QChar}s.)
\l{Unicode} is an international standard that supports most of the
writing systems in use today. It is a superset of US-ASCII (ANSI
@@ -1727,17 +1737,15 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
store raw bytes and traditional 8-bit '\\0'-terminated strings.
For most purposes, QString is the class you want to use. It is
used throughout the Qt API, and the Unicode support ensures that
- your applications will be easy to translate if you want to expand
- your application's market at some point. The two main cases where
- QByteArray is appropriate are when you need to store raw binary
- data, and when memory conservation is critical (like in embedded
- systems).
-
- \tableofcontents
+ your applications are easy to translate if you want to expand
+ your application's market at some point. Two prominent cases
+ where QByteArray is appropriate are when you need to store raw
+ binary data, and when memory conservation is critical (like in
+ embedded systems).
- \section1 Initializing a String
+ \section1 Initializing a string
- One way to initialize a QString is simply to pass a \c{const char
+ One way to initialize a QString is to pass a \c{const char
*} to its constructor. For example, the following code creates a
QString of size 5 containing the data "Hello":
@@ -1748,17 +1756,18 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
In all of the QString functions that take \c{const char *}
parameters, the \c{const char *} is interpreted as a classic
- C-style '\\0'-terminated string encoded in UTF-8. It is legal for
- the \c{const char *} parameter to be \nullptr.
+ C-style \c{'\\0'}-terminated string. Except where the function's
+ name overtly indicates some other encoding, such \c{const char *}
+ parameters are assumed to be encoded in UTF-8.
You can also provide string data as an array of \l{QChar}s:
\snippet qstring/main.cpp 1
QString makes a deep copy of the QChar data, so you can modify it
- later without experiencing side effects. (If for performance
- reasons you don't want to take a deep copy of the character data,
- use QString::fromRawData() instead.)
+ later without experiencing side effects. You can avoid taking a
+ deep copy of the character data by using QStringView or
+ QString::fromRawData() instead.
Another approach is to set the size of the string using resize()
and to initialize the data character per character. QString uses
@@ -1775,7 +1784,7 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\snippet qstring/main.cpp 3
- The at() function can be faster than \l operator[](), because it
+ The at() function can be faster than \l operator[]() because it
never causes a \l{deep copy} to occur. Alternatively, use the
first(), last(), or sliced() functions to extract several characters
at a time.
@@ -1797,11 +1806,11 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
You can also pass string literals to functions that take QStrings
as arguments, invoking the QString(const char *)
constructor. Similarly, you can pass a QString to a function that
- takes a \c{const char *} argument using the \l qPrintable() macro
+ takes a \c{const char *} argument using the \l qPrintable() macro,
which returns the given QString as a \c{const char *}. This is
equivalent to calling <QString>.toLocal8Bit().constData().
- \section1 Manipulating String Data
+ \section1 Manipulating string data
QString provides the following basic functions for modifying the
character data: append(), prepend(), insert(), replace(), and
@@ -1809,19 +1818,19 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\snippet qstring/main.cpp 5
- In the above example the replace() function's first two arguments are the
+ In the above example, the replace() function's first two arguments are the
position from which to start replacing and the number of characters that
should be replaced.
When data-modifying functions increase the size of the string,
- they may lead to reallocation of memory for the QString object. When
+ QString may reallocate the memory in which it holds its data. When
this happens, QString expands by more than it immediately needs so as
to have space for further expansion without reallocation until the size
- of the string has greatly increased.
+ of the string has significantly increased.
- The insert(), remove() and, when replacing a sub-string with one of
+ The insert(), remove(), and, when replacing a sub-string with one of
different size, replace() functions can be slow (\l{linear time}) for
- large strings, because they require moving many characters in the string
+ large strings because they require moving many characters in the string
by at least one position in memory.
If you are building a QString gradually and know in advance
@@ -1839,32 +1848,32 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
method of the QString is called. Accessing such an iterator or reference
after the call to a non-\c{const} method leads to undefined behavior. When
stability for iterator-like functionality is required, you should use
- indexes instead of iterators as they are not tied to QString's internal
+ indexes instead of iterators, as they are not tied to QString's internal
state and thus do not get invalidated.
\note Due to \l{implicit sharing}, the first non-\c{const} operator or
- function used on a given QString may cause it to, internally, perform a deep
+ function used on a given QString may cause it to internally perform a deep
copy of its data. This invalidates all iterators over the string and
- references to individual characters within it. After the first non-\c{const}
- operator, operations that modify QString may completely (in case of
- reallocation) or partially invalidate iterators and references, but other
- methods (such as begin() or end()) will not. Accessing an iterator or
- reference after it has been invalidated leads to undefined behavior.
-
- A frequent requirement is to remove whitespace characters from a
- string ('\\n', '\\t', ' ', etc.). If you want to remove whitespace
- from both ends of a QString, use the trimmed() function. If you
- want to remove whitespace from both ends and replace multiple
- consecutive whitespaces with a single space character within the
- string, use simplified().
+ references to individual characters within it. Do not call non-const
+ functions while keeping iterators. Accessing an iterator or reference
+ after it has been invalidated leads to undefined behavior. See the
+ \l{Implicit sharing iterator problem} section for more information.
+
+ A frequent requirement is to remove or simplify the spacing between
+ visible characters in a string. The characters that make up that spacing
+ are those for which \l {QChar::}{isSpace()} returns \c true, such as
+ the simple space \c{' '}, the horizontal tab \c{'\\t'} and the newline \c{'\\n'}.
+ To obtain a copy of a string leaving out any spacing from its start and end,
+ use \l trimmed(). To also replace each sequence of spacing characters within
+ the string with a simple space, \c{' '}, use \l simplified().
If you want to find all occurrences of a particular character or
substring in a QString, use the indexOf() or lastIndexOf()
- functions. The former searches forward starting from a given index
- position, the latter searches backward. Both return the index
- position of the character or substring if they find it; otherwise,
- they return -1. For example, here is a typical loop that finds all
- occurrences of a particular substring:
+ functions.The former searches forward, the latter searches backward.
+ Either can be told an index position from which to start their search.
+ Each returns the index position of the character or substring if they
+ find it; otherwise, they return -1. For example, here is a typical loop
+ that finds all occurrences of a particular substring:
\snippet qstring/main.cpp 6
@@ -1873,52 +1882,57 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
setNum() functions, the number() static functions, and the
toInt(), toDouble(), and similar functions.
- To get an upper- or lowercase version of a string use toUpper() or
+ To get an uppercase or lowercase version of a string, use toUpper() or
toLower().
Lists of strings are handled by the QStringList class. You can
split a string into a list of strings using the split() function,
and join a list of strings into a single string with an optional
- separator using QStringList::join(). You can obtain a list of
- strings from a string list that contain a particular substring or
- that match a particular QRegularExpression using the QStringList::filter()
- function.
+ separator using QStringList::join(). You can obtain a filtered list
+ from a string list by selecting the entries in it that contain a
+ particular substring or match a particular QRegularExpression.
+ See QStringList::filter() for details.
- \section1 Querying String Data
+ \section1 Querying string data
- If you want to see if a QString starts or ends with a particular
- substring use startsWith() or endsWith(). If you simply want to
- check whether a QString contains a particular character or
- substring, use the contains() function. If you want to find out
- how many times a particular character or substring occurs in the
- string, use count().
+ To see if a QString starts or ends with a particular substring, use
+ startsWith() or endsWith(). To check whether a QString contains a
+ specific character or substring, use the contains() function. To
+ find out how many times a particular character or substring occurs
+ in a string, use count().
To obtain a pointer to the actual character data, call data() or
constData(). These functions return a pointer to the beginning of
the QChar data. The pointer is guaranteed to remain valid until a
non-\c{const} function is called on the QString.
- \section2 Comparing Strings
+ \section2 Comparing strings
QStrings can be compared using overloaded operators such as \l
operator<(), \l operator<=(), \l operator==(), \l operator>=(),
- and so on. Note that the comparison is based exclusively on the
- numeric Unicode values of the characters. It is very fast, but is
- not what a human would expect; the QString::localeAwareCompare()
- function is usually a better choice for sorting user-interface
- strings, when such a comparison is available.
-
- On Unix-like platforms (including Linux, \macos and iOS), when Qt
- is linked with the ICU library (which it usually is), its
- locale-aware sorting is used. Otherwise, on \macos and iOS, \l
- localeAwareCompare() compares according the "Order for sorted
- lists" setting in the International preferences panel. On other
- Unix-like systems without ICU, the comparison falls back to the
- system library's \c strcoll(),
-
- \section1 Converting Between Encoded Strings Data and QString
-
- QString provides the following three functions that return a
+ and so on. The comparison is based exclusively on the lexicographical
+ order of the two strings, seen as sequences of UTF-16 code units.
+ It is very fast but is not what a human would expect; the
+ QString::localeAwareCompare() function is usually a better choice for
+ sorting user-interface strings, when such a comparison is available.
+
+ When Qt is linked with the ICU library (which it usually is), its
+ locale-aware sorting is used. Otherwise, platform-specific solutions
+ are used:
+ \list
+ \li On Windows, localeAwareCompare() uses the current user locale,
+ as set in the \uicontrol{regional} and \uicontrol{language}
+ options portion of \uicontrol{Control Panel}.
+ \li On \macos and iOS, \l localeAwareCompare() compares according
+ to the \uicontrol{Order for sorted lists} setting in the
+ \uicontrol{International preferences} panel.
+ \li On other Unix-like systems, the comparison falls back to the
+ system library's \c strcoll().
+ \endlist
+
+ \section1 Converting between encoded string data and QString
+
+ QString provides the following functions that return a
\c{const char *} version of the string as QByteArray: toUtf8(),
toLatin1(), and toLocal8Bit().
@@ -1949,7 +1963,7 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\li \l QT_NO_CAST_FROM_ASCII disables automatic conversions from
C string literals and pointers to Unicode.
\li \l QT_RESTRICTED_CAST_FROM_ASCII allows automatic conversions
- from C characters and character arrays, but disables automatic
+ from C characters and character arrays but disables automatic
conversions from character pointers to Unicode.
\li \l QT_NO_CAST_TO_ASCII disables automatic conversion from QString
to C strings.
@@ -1957,7 +1971,7 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
You then need to explicitly call fromUtf8(), fromLatin1(),
or fromLocal8Bit() to construct a QString from an
- 8-bit string, or use the lightweight QLatin1StringView class, for
+ 8-bit string, or use the lightweight QLatin1StringView class. For
example:
\snippet code/src_corelib_text_qstring.cpp 1
@@ -1978,7 +1992,7 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\snippet qstring/main.cpp 7
- The \c result variable, is a normal variable allocated on the
+ The \c result variable is a normal variable allocated on the
stack. When \c return is called, and because we're returning by
value, the copy constructor is called and a copy of the string is
returned. No actual copying takes place thanks to the implicit
@@ -1986,12 +2000,12 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\endtable
- \section1 Distinction Between Null and Empty Strings
+ \section1 Distinction between null and empty strings
- For historical reasons, QString distinguishes between a null
- string and an empty string. A \e null string is a string that is
+ For historical reasons, QString distinguishes between null
+ and empty strings. A \e null string is a string that is
initialized using QString's default constructor or by passing
- (\c{const char *})0 to the constructor. An \e empty string is any
+ \nullptr to the constructor. An \e empty string is any
string with size 0. A null string is always empty, but an empty
string isn't necessarily null:
@@ -1999,10 +2013,10 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
All functions except isNull() treat null strings the same as empty
strings. For example, toUtf8().constData() returns a valid pointer
- (\e not nullptr) to a '\\0' character for a null string. We
+ (not \nullptr) to a '\\0' character for a null string. We
recommend that you always use the isEmpty() function and avoid isNull().
- \section1 Number Formats
+ \section1 Number formats
When a QString::arg() \c{'%'} format specifier includes the \c{'L'} locale
qualifier, and the base is ten (its default), the default locale is
@@ -2012,16 +2026,16 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
C locale's representation of numbers.
When QString::arg() applies left-padding to numbers, the fill character
- \c{'0'} is treated specially. If the number is negative, its minus sign will
- appear before the zero-padding. If the field is localized, the
+ \c{'0'} is treated specially. If the number is negative, its minus sign
+ appears before the zero-padding. If the field is localized, the
locale-appropriate zero character is used in place of \c{'0'}. For
floating-point numbers, this special treatment only applies if the number is
finite.
- \section2 Floating-point Formats
+ \section2 Floating-point formats
- In member functions (e.g., arg(), number()) that represent floating-point
- numbers (\c float or \c double) as strings, the form of display can be
+ In member functions (for example, arg() and number()) that format floating-point
+ numbers (\c float or \c double) as strings, the representation used can be
controlled by a choice of \e format and \e precision, whose meanings are as
for \l {QLocale::toString(double, char, int)}.
@@ -2030,19 +2044,15 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
the exponent shows its sign and includes at least two digits, left-padding
with zero if needed.
- \section1 More Efficient String Construction
-
- Many strings are known at compile time. But the trivial
- constructor QString("Hello"), will copy the contents of the string,
- treating the contents as Latin-1. To avoid this, one can use the
- QStringLiteral macro to directly create the required data at compile
- time. Constructing a QString out of the literal does then not cause
- any overhead at runtime.
+ \section1 More efficient string construction
- A slightly less efficient way is to use QLatin1StringView. This class wraps
- a C string literal, precalculates it length at compile time and can
- then be used for faster comparison with QStrings and conversion to
- QStrings than a regular C string literal.
+ Many strings are known at compile time. The QString constructor from
+ C++ string literals will copy the contents of the string,
+ treating the contents as UTF-8. This requires memory allocation and
+ re-encoding string data, operations that will happen at runtime.
+ If the string data is known at compile time, you can use the QStringLiteral
+ macro or similarly \c{operator""_s} to create QString's payload at compile
+ time instead.
Using the QString \c{'+'} operator, it is easy to construct a
complex string from multiple substrings. You will often write code
@@ -2051,16 +2061,15 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
\snippet qstring/stringbuilder.cpp 0
There is nothing wrong with either of these string constructions,
- but there are a few hidden inefficiencies. Beginning with Qt 4.6,
- you can eliminate them.
+ but there are a few hidden inefficiencies:
- First, multiple uses of the \c{'+'} operator usually means
+ First, repeated use of the \c{'+'} operator may lead to
multiple memory allocations. When concatenating \e{n} substrings,
where \e{n > 2}, there can be as many as \e{n - 1} calls to the
memory allocator.
- In 4.6, an internal template class \c{QStringBuilder} has been
- added along with a few helper functions. This class is marked
+ These allocations can be optimized by an internal class
+ \c{QStringBuilder}. This class is marked
internal and does not appear in the documentation, because you
aren't meant to instantiate it in your code. Its use will be
automatic, as described below. The class is found in
@@ -2076,54 +2085,57 @@ void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *whe
then called \e{once} to get the required space, and the substrings
are copied into it one by one.
- Additional efficiency is gained by inlining and reduced reference
- counting (the QString created from a \c{QStringBuilder} typically
+ Additional efficiency is gained by inlining and reducing reference
+ counting (the QString created from a \c{QStringBuilder}
has a ref count of 1, whereas QString::append() needs an extra
test).
There are two ways you can access this improved method of string
construction. The straightforward way is to include
- \c{QStringBuilder} wherever you want to use it, and use the
+ \c{QStringBuilder} wherever you want to use it and use the
\c{'%'} operator instead of \c{'+'} when concatenating strings:
\snippet qstring/stringbuilder.cpp 5
- A more global approach, which is more convenient but not entirely source
- compatible, is to define \c QT_USE_QSTRINGBUILDER (by adding it to the compiler
- flags) at build time. This will make concatenating strings with \c{'+'} work the
- same way as \c{QStringBuilder} \c{'%'}.
+ A more global approach, which is more convenient but not entirely
+ source-compatible, is to define \c QT_USE_QSTRINGBUILDER (by adding
+ it to the compiler flags) at build time. This will make concatenating
+ strings with \c{'+'} work the same way as \c{QStringBuilder's} \c{'%'}.
+
+ \note Using automatic type deduction (for example, by using the \c
+ auto keyword) with the result of string concatenation when QStringBuilder
+ is enabled will show that the concatenation is indeed an object of a
+ QStringBuilder specialization:
- \note Take care when using the \c auto keyword with the result of
- string concatenation using QStringBuilder:
\snippet qstring/stringbuilder.cpp 6
- Typically this is not what is expected (and can result in undefined behavior).
- This issue can be fixed by specifying the return type:
- \snippet qstring/stringbuilder.cpp 7
+ This does not cause any harm, as QStringBuilder will implicitly convert to
+ QString when required. If this is undesirable, then one should specify
+ the necessary types instead of having the compiler deduce them:
- \note \l {https://invent.kde.org/sdk/clazy} {Clazy} has a check, auto-unexpected-qstringbuilder,
- that catches this issue.
+ \snippet qstring/stringbuilder.cpp 7
- \section1 Maximum Size and Out-of-memory Conditions
+ \section1 Maximum size and out-of-memory conditions
The maximum size of QString depends on the architecture. Most 64-bit
systems can allocate more than 2 GB of memory, with a typical limit
of 2^63 bytes. The actual value also depends on the overhead required for
- managing the data block. As a result, you can expect the maximum size
- of 2 GB minus overhead on 32-bit platforms, and 2^63 bytes minus overhead
+ managing the data block. As a result, you can expect a maximum size
+ of 2 GB minus overhead on 32-bit platforms and 2^63 bytes minus overhead
on 64-bit platforms. The number of elements that can be stored in a
QString is this maximum size divided by the size of QChar.
When memory allocation fails, QString throws a \c std::bad_alloc
exception if the application was compiled with exception support.
- Out of memory conditions in Qt containers are the only case where Qt
+ Out-of-memory conditions in Qt containers are the only cases where Qt
will throw exceptions. If exceptions are disabled, then running out of
memory is undefined behavior.
- 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.
+ \note Target operating systems may impose limits on how much memory an
+ application can allocate, in total, or on the size of individual allocations.
+ This may further restrict the size of string a QString can hold.
+ Mitigating or controlling the behavior these limits cause is beyond the
+ scope of the Qt API.
\sa fromRawData(), QChar, QStringView, QLatin1StringView, QByteArray
*/
@@ -2409,8 +2421,8 @@ encoded in \1, and is converted to QString using the \2 function.
/*! \fn std::wstring QString::toStdWString() const
Returns a std::wstring object with the data contained in this
- QString. The std::wstring is encoded in utf16 on platforms where
- wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms
+ QString. The std::wstring is encoded in UTF-16 on platforms where
+ wchar_t is 2 bytes wide (for example, Windows) and in UTF-32 on platforms
where wchar_t is 4 bytes wide (most Unix systems).
This method is mostly useful to pass a QString to a function
@@ -2483,15 +2495,12 @@ QString::QString(const QChar *unicode, qsizetype size)
if (!unicode) {
d.clear();
} else {
- if (size < 0) {
- size = 0;
- while (!unicode[size].isNull())
- ++size;
- }
+ if (size < 0)
+ size = QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(unicode));
if (!size) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(size), size);
+ d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
memcpy(d.data(), unicode, size * sizeof(QChar));
d.data()[size] = '\0';
@@ -2510,7 +2519,7 @@ QString::QString(qsizetype size, QChar ch)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(size), size);
+ d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
char16_t *b = d.data();
@@ -2531,7 +2540,7 @@ QString::QString(qsizetype size, Qt::Initialization)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(size), size);
+ d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
}
@@ -2549,7 +2558,7 @@ QString::QString(qsizetype size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
- d = DataPointer(Data::allocate(1), 1);
+ d = DataPointer(1, 1);
Q_CHECK_PTR(d.data());
d.data()[0] = ch.unicode();
d.data()[1] = '\0';
@@ -2565,7 +2574,7 @@ QString::QString(QChar ch)
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
- \note: any null ('\\0') bytes in the byte array will be included in this
+ \note Any null ('\\0') bytes in the byte array will be included in this
string, converted to Unicode null characters (U+0000). This behavior is
different from Qt 5.x.
@@ -2613,6 +2622,12 @@ QString::QString(QChar ch)
\internal
*/
+/*! \fn QString::operator std::u16string_view() const
+ \since 6.7
+
+ Converts this QString object to a \c{std::u16string_view} object.
+*/
+
static bool needsReallocate(const QString &str, qsizetype newSize)
{
const auto capacityAtEnd = str.capacity() - str.data_ptr().freeSpaceAtBegin();
@@ -2681,6 +2696,24 @@ void QString::resize(qsizetype newSize, QChar fillChar)
std::fill_n(d.data() + oldSize, difference, fillChar.unicode());
}
+
+/*!
+ \since 6.8
+
+ Sets the size of the string to \a size characters. If the size of
+ the string grows, the new characters are uninitialized.
+
+ The behavior is identical to \c{resize(size)}.
+
+ \sa resize()
+*/
+
+void QString::resizeForOverwrite(qsizetype size)
+{
+ resize(size);
+}
+
+
/*! \fn qsizetype QString::capacity() const
Returns the maximum number of characters that can be stored in
@@ -2706,20 +2739,20 @@ void QString::resize(qsizetype newSize, QChar fillChar)
Ensures the string has space for at least \a size characters.
- If you know in advance how large the string will be, you can call this
- function to save repeated reallocation in the course of building it.
+ If you know in advance how large a string will be, you can call this
+ function to save repeated reallocation while building it.
This can improve performance when building a string incrementally.
A long sequence of operations that add to a string may trigger several
reallocations, the last of which may leave you with significantly more
- space than you really need, which is less efficient than doing a single
+ space than you need. This is less efficient than doing a single
allocation of the right size at the start.
If in doubt about how much space shall be needed, it is usually better to
use an upper bound as \a size, or a high estimate of the most likely size,
if a strict upper bound would be much bigger than this. If \a size is an
underestimate, the string will grow as needed once the reserved size is
- exceeded, which may lead to a larger allocation than your best overestimate
- would have and will slow the operation that triggers it.
+ exceeded, which may lead to a larger allocation than your best
+ overestimate would have and will slow the operation that triggers it.
\warning reserve() reserves memory but does not change the size of the
string. Accessing data beyond the end of the string is undefined behavior.
@@ -2761,7 +2794,7 @@ void QString::reallocData(qsizetype alloc, QArrayData::AllocationOption option)
const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0;
if (d->needsDetach() || cannotUseReallocate) {
- DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
+ DataPointer dd(alloc, qMin(alloc, d.size), option);
Q_CHECK_PTR(dd.data());
if (dd.size > 0)
::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
@@ -2867,16 +2900,7 @@ QString &QString::operator=(QLatin1StringView other)
*/
QString &QString::operator=(QChar ch)
{
- const qsizetype capacityAtEnd = capacity() - d.freeSpaceAtBegin();
- if (isDetached() && capacityAtEnd >= 1) { // assumes d->alloc == 0 -> !isDetached() (sharedNull)
- // re-use existing capacity:
- d.data()[0] = ch.unicode();
- d.data()[1] = 0;
- d.size = 1;
- } else {
- operator=(QString(ch));
- }
- return *this;
+ return assign(1, ch);
}
/*!
@@ -3057,11 +3081,10 @@ QString &QString::insert(qsizetype i, QUtf8StringView s)
} else {
// Optimal insertion of Utf8 data is at the end, anywhere else could
// potentially lead to moving characters twice if Utf8 data size
- // (variable-width) is less than the equiavalent Utf16 data size
+ // (variable-width) is less than the equivalent Utf16 data size
QVarLengthArray<char16_t> buffer(insert_size); // ### optimize (QTBUG-108546)
char16_t *b = QUtf8::convertToUnicode(buffer.data(), s);
- buffer.resize(std::distance(buffer.begin(), b));
- insert_helper(*this, i, buffer);
+ insert_helper(*this, i, QStringView(buffer.data(), b));
}
return *this;
@@ -3086,7 +3109,8 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size)
// In case when data points into "this"
if (!d->needsDetach() && QtPrivate::q_points_into_range(unicode, *this)) {
- insert_helper(*this, i, QVarLengthArray<QChar>(unicode, unicode + size));
+ QVarLengthArray copy(unicode, unicode + size);
+ insert(i, copy.data(), size);
} else {
insert_helper(*this, i, QStringView(unicode, size));
}
@@ -3134,7 +3158,10 @@ QString &QString::append(const QString &str)
{
if (!str.isNull()) {
if (isNull()) {
- operator=(str);
+ if (Q_UNLIKELY(!str.d.isMutable()))
+ assign(str); // fromRawData, so we do a deep copy
+ else
+ operator=(str);
} else if (str.size()) {
append(str.constData(), str.size());
}
@@ -3310,6 +3337,111 @@ QString &QString::append(QChar ch)
*/
/*!
+ \fn QString &QString::assign(QAnyStringView v)
+ \since 6.6
+
+ Replaces the contents of this string with a copy of \a v and returns a
+ reference to this string.
+
+ The size of this string will be equal to the size of \a v, converted to
+ UTF-16 as if by \c{v.toString()}. Unlike QAnyStringView::toString(), however,
+ this function only allocates memory if the estimated size exceeds the capacity
+ of this string or this string is shared.
+
+ \sa QAnyStringView::toString()
+*/
+
+/*!
+ \fn QString &QString::assign(qsizetype n, QChar c)
+ \since 6.6
+
+ Replaces the contents of this string with \a n copies of \a c and
+ returns a reference to this string.
+
+ The size of this string will be equal to \a n, which has to be non-negative.
+
+ This function will only allocate memory if \a n exceeds the capacity of this
+ string or this string is shared.
+
+ \sa fill()
+*/
+
+/*!
+ \fn template <typename InputIterator, QString::if_compatible_iterator<InputIterator>> QString &QString::assign(InputIterator first, InputIterator last)
+ \since 6.6
+
+ Replaces the contents of this string with a copy of the elements in the
+ iterator range [\a first, \a last) and returns a reference to this string.
+
+ The size of this string will be equal to the decoded length of the elements
+ in the range [\a first, \a last), which need not be the same as the length of
+ the range itself, because this function transparently recodes the input
+ character set to UTF-16.
+
+ This function will only allocate memory if the number of elements in the
+ range, or, for non-UTF-16-encoded input, the maximum possible size of the
+ resulting string, exceeds the capacity of this string, or if this string is
+ shared.
+
+ \note This function overload only participates in overload resolution if
+ \c InputIterator meets the requirements of a
+ \l {https://en.cppreference.com/w/cpp/named_req/InputIterator} {LegacyInputIterator}
+ and the \c{value_type} of \c InputIterator is one of the following character types:
+ \list
+ \li QChar
+ \li QLatin1Char
+ \li \c {char}
+ \li \c {unsigned char}
+ \li \c {signed char}
+ \li \c {char8_t}
+ \li \c char16_t
+ \li (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t
+ \li \c char32_t
+ \endlist
+
+ \note The behavior is undefined if either argument is an iterator into *this or
+ [\a first, \a last) is not a valid range.
+*/
+
+QString &QString::assign(QAnyStringView s)
+{
+ if (s.size() <= capacity() && isDetached()) {
+ const auto offset = d.freeSpaceAtBegin();
+ if (offset)
+ d.setBegin(d.begin() - offset);
+ resize(0);
+ s.visit([this](auto input) {
+ this->append(input);
+ });
+ } else {
+ *this = s.toString();
+ }
+ return *this;
+}
+
+#ifndef QT_BOOTSTRAPPED
+QString &QString::assign_helper(const char32_t *data, qsizetype len)
+{
+ // worst case: each char32_t requires a surrogate pair, so
+ const auto requiredCapacity = len * 2;
+ if (requiredCapacity <= capacity() && isDetached()) {
+ const auto offset = d.freeSpaceAtBegin();
+ if (offset)
+ d.setBegin(d.begin() - offset);
+ auto begin = reinterpret_cast<QChar *>(d.begin());
+ auto ba = QByteArrayView(reinterpret_cast<const std::byte*>(data), len * sizeof(char32_t));
+ QStringConverter::State state;
+ const auto end = QUtf32::convertToUnicode(begin, ba, &state, DetectEndianness);
+ d.size = end - begin;
+ d.data()[d.size] = u'\0';
+ } else {
+ *this = QString::fromUcs4(data, len);
+ }
+ return *this;
+}
+#endif
+
+/*!
\fn QString &QString::remove(qsizetype position, qsizetype n)
Removes \a n characters from the string, starting at the given \a
@@ -3522,7 +3654,7 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
it = std::remove_copy_if(first_match + 1, end, it, match);
copy.d.size = std::distance(dst, it);
copy.d.data()[copy.d.size] = u'\0';
- *this = copy;
+ *this = std::move(copy);
}
return *this;
}
@@ -3557,7 +3689,7 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
and there isn't enough capacity, create a new string, copy characters to it
as needed, then swap it with "str".
*/
-static void replace_with_copy(QString &str, size_t *indices, qsizetype nIndices, qsizetype blen,
+static void replace_with_copy(QString &str, QSpan<size_t> indices, qsizetype blen,
QStringView after)
{
const qsizetype alen = after.size();
@@ -3565,12 +3697,12 @@ static void replace_with_copy(QString &str, size_t *indices, qsizetype nIndices,
const QString::DataPointer &str_d = str.data_ptr();
auto src_start = str_d.begin();
- const qsizetype newSize = str_d.size + nIndices * (alen - blen);
+ const qsizetype newSize = str_d.size + indices.size() * (alen - blen);
QString copy{ newSize, Qt::Uninitialized };
QString::DataPointer &copy_d = copy.data_ptr();
auto dst = copy_d.begin();
- for (int i = 0; i < nIndices; ++i) {
- auto hit = str_d.begin() + indices[i];
+ for (size_t index : indices) {
+ auto hit = str_d.begin() + index;
dst = std::copy(src_start, hit, dst);
dst = std::copy_n(after_b, alen, dst);
src_start = hit + blen;
@@ -3580,7 +3712,7 @@ static void replace_with_copy(QString &str, size_t *indices, qsizetype nIndices,
}
// No detaching or reallocation is needed
-static void replace_in_place(QString &str, size_t *indices, qsizetype nIndices,
+static void replace_in_place(QString &str, QSpan<size_t> indices,
qsizetype blen, QStringView after)
{
const qsizetype alen = after.size();
@@ -3588,16 +3720,16 @@ static void replace_in_place(QString &str, size_t *indices, qsizetype nIndices,
const char16_t *after_e = after.utf16() + after.size();
if (blen == alen) { // Replace in place
- for (qsizetype i = 0; i < nIndices; ++i)
- std::copy_n(after_b, alen, str.data_ptr().begin() + indices[i]);
+ for (size_t index : indices)
+ std::copy_n(after_b, alen, str.data_ptr().begin() + index);
} else if (blen > alen) { // Replace from front
char16_t *begin = str.data_ptr().begin();
- char16_t *hit = begin + indices[0];
+ char16_t *hit = begin + indices.front();
char16_t *to = hit;
to = std::copy_n(after_b, alen, to);
char16_t *movestart = hit + blen;
- for (qsizetype i = 1; i < nIndices; ++i) {
- hit = begin + indices[i];
+ for (size_t index : indices.sliced(1)) {
+ hit = begin + index;
to = std::move(movestart, hit, to);
to = std::copy_n(after_b, alen, to);
movestart = hit + blen;
@@ -3606,7 +3738,7 @@ static void replace_in_place(QString &str, size_t *indices, qsizetype nIndices,
str.resize(std::distance(begin, to));
} else { // blen < alen, Replace from back
const qsizetype oldSize = str.data_ptr().size;
- const qsizetype adjust = nIndices * (alen - blen);
+ const qsizetype adjust = indices.size() * (alen - blen);
const qsizetype newSize = oldSize + adjust;
str.resize(newSize);
@@ -3614,9 +3746,8 @@ static void replace_in_place(QString &str, size_t *indices, qsizetype nIndices,
char16_t *moveend = begin + oldSize;
char16_t *to = str.data_ptr().end();
- while (nIndices) {
- --nIndices;
- char16_t *hit = begin + indices[nIndices];
+ for (auto it = indices.rbegin(), end = indices.rend(); it != end; ++it) {
+ char16_t *hit = begin + *it;
char16_t *movestart = hit + blen;
to = std::move_backward(movestart, moveend, to);
to = std::copy_backward(after_b, after_e, to);
@@ -3625,22 +3756,22 @@ static void replace_in_place(QString &str, size_t *indices, qsizetype nIndices,
}
}
-static void replace_helper(QString &str, size_t *indices, qsizetype nIndices, qsizetype blen, QStringView after)
+static void replace_helper(QString &str, QSpan<size_t> indices, qsizetype blen, QStringView after)
{
const qsizetype oldSize = str.data_ptr().size;
- const qsizetype adjust = nIndices * (after.size() - blen);
+ const qsizetype adjust = indices.size() * (after.size() - blen);
const qsizetype newSize = oldSize + adjust;
if (str.data_ptr().needsDetach() || needsReallocate(str, newSize)) {
- replace_with_copy(str, indices, nIndices, blen, after);
+ replace_with_copy(str, indices, blen, after);
return;
}
if (QtPrivate::q_points_into_range(after.begin(), str))
// Copy after if it lies inside our own d.b area (which we could
// possibly invalidate via a realloc or modify by replacement)
- replace_in_place(str, indices, nIndices, blen, QVarLengthArray(after.begin(), after.end()));
+ replace_in_place(str, indices, blen, QVarLengthArray(after.begin(), after.end()));
else
- replace_in_place(str, indices, nIndices, blen, after);
+ replace_in_place(str, indices, blen, after);
}
/*!
@@ -3679,7 +3810,7 @@ QString &QString::replace(qsizetype pos, qsizetype len, const QChar *after, qsiz
len = this->size() - pos;
size_t index = pos;
- replace_helper(*this, &index, 1, len, QStringView{after, alen});
+ replace_helper(*this, QSpan(&index, 1), len, QStringView{after, alen});
return *this;
}
@@ -3758,7 +3889,7 @@ QString &QString::replace(const QChar *before, qsizetype blen,
if (indices.isEmpty())
return *this;
- replace_helper(*this, indices.data(), indices.size(), blen, QStringView{after, alen});
+ replace_helper(*this, indices, blen, QStringView{after, alen});
return *this;
}
@@ -3800,7 +3931,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
if (indices.isEmpty())
return *this;
- replace_helper(*this, indices.data(), indices.size(), 1, after);
+ replace_helper(*this, indices, 1, after);
return *this;
}
@@ -3939,10 +4070,10 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
}
/*!
- \fn bool QString::operator==(const QString &s1, const QString &s2)
+ \fn bool QString::operator==(const QString &lhs, const QString &rhs)
\overload operator==()
- Returns \c true if string \a s1 is equal to string \a s2; otherwise
+ Returns \c true if string \a lhs is equal to string \a rhs; otherwise
returns \c false.
\include qstring.cpp compare-isNull-vs-isEmpty
@@ -3951,45 +4082,43 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
*/
/*!
- \fn bool QString::operator==(const QString &s1, QLatin1StringView s2)
+ \fn bool QString::operator==(const QString &lhs, const QLatin1StringView &rhs)
\overload operator==()
- Returns \c true if \a s1 is equal to \a s2; otherwise
+ Returns \c true if \a lhs is equal to \a rhs; otherwise
returns \c false.
*/
/*!
- \fn bool QString::operator==(QLatin1StringView s1, const QString &s2)
+ \fn bool QString::operator==(const QLatin1StringView &lhs, const QString &rhs)
\overload operator==()
- Returns \c true if \a s1 is equal to \a s2; otherwise
+ Returns \c true if \a lhs is equal to \a rhs; otherwise
returns \c false.
*/
-/*! \fn bool QString::operator==(const QByteArray &other) const
+/*! \fn bool QString::operator==(const QString &lhs, const QByteArray &rhs)
\overload operator==()
- The \a other byte array is converted to a QString using the
- fromUtf8() function.
+ The \a rhs byte array is converted to a QUtf8StringView.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
can be useful if you want to ensure that all user-visible strings
go through QObject::tr(), for example.
- Returns \c true if this string is lexically equal to the parameter
- string \a other. Otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically equal to \a rhs.
+ Otherwise returns \c false.
*/
-/*! \fn bool QString::operator==(const char *other) const
+/*! \fn bool QString::operator==(const QString &lhs, const char * const &rhs)
\overload operator==()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -3998,41 +4127,41 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
*/
/*!
- \fn bool QString::operator<(const QString &s1, const QString &s2)
+ \fn bool QString::operator<(const QString &lhs, const QString &rhs)
\overload operator<()
- Returns \c true if string \a s1 is lexically less than string
- \a s2; otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically less than string
+ \a rhs; otherwise returns \c false.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator<(const QString &s1, QLatin1StringView s2)
+ \fn bool QString::operator<(const QString &lhs, const QLatin1StringView &rhs)
\overload operator<()
- Returns \c true if \a s1 is lexically less than \a s2;
+ Returns \c true if \a lhs is lexically less than \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QString::operator<(QLatin1StringView s1, const QString &s2)
+ \fn bool QString::operator<(const QLatin1StringView &lhs, const QString &rhs)
\overload operator<()
- Returns \c true if \a s1 is lexically less than \a s2;
+ Returns \c true if \a lhs is lexically less than \a rhs;
otherwise returns \c false.
*/
-/*! \fn bool QString::operator<(const QByteArray &other) const
+/*! \fn bool QString::operator<(const QString &lhs, const QByteArray &rhs)
\overload operator<()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
You can disable this operator
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4040,15 +4169,14 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator<(const char *other) const
+/*! \fn bool QString::operator<(const QString &lhs, const char * const &rhs)
- Returns \c true if this string is lexically less than string \a other.
+ Returns \c true if string \a lhs is lexically less than string \a rhs.
Otherwise returns \c false.
\overload operator<()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4056,39 +4184,39 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator<=(const QString &s1, const QString &s2)
+/*! \fn bool QString::operator<=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically less than or equal to
- string \a s2; otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically less than or equal to
+ string \a rhs; otherwise returns \c false.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator<=(const QString &s1, QLatin1StringView s2)
+ \fn bool QString::operator<=(const QString &lhs, const QLatin1StringView &rhs)
\overload operator<=()
- Returns \c true if \a s1 is lexically less than or equal to \a s2;
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QString::operator<=(QLatin1StringView s1, const QString &s2)
+ \fn bool QString::operator<=(const QLatin1StringView &lhs, const QString &rhs)
\overload operator<=()
- Returns \c true if \a s1 is lexically less than or equal to \a s2;
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
otherwise returns \c false.
*/
-/*! \fn bool QString::operator<=(const QByteArray &other) const
+/*! \fn bool QString::operator<=(const QString &lhs, const QByteArray &rhs)
\overload operator<=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4096,12 +4224,11 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator<=(const char *other) const
+/*! \fn bool QString::operator<=(const QString &lhs, const char * const &rhs)
\overload operator<=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4109,39 +4236,39 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator>(const QString &s1, const QString &s2)
+/*! \fn bool QString::operator>(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically greater than string \a s2;
+ Returns \c true if string \a lhs is lexically greater than string \a rhs;
otherwise returns \c false.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator>(const QString &s1, QLatin1StringView s2)
+ \fn bool QString::operator>(const QString &lhs, const QLatin1StringView &rhs)
\overload operator>()
- Returns \c true if \a s1 is lexically greater than \a s2;
+ Returns \c true if \a lhs is lexically greater than \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QString::operator>(QLatin1StringView s1, const QString &s2)
+ \fn bool QString::operator>(const QLatin1StringView &lhs, const QString &rhs)
\overload operator>()
- Returns \c true if \a s1 is lexically greater than \a s2;
+ Returns \c true if \a lhs is lexically greater than \a rhs;
otherwise returns \c false.
*/
-/*! \fn bool QString::operator>(const QByteArray &other) const
+/*! \fn bool QString::operator>(const QString &lhs, const QByteArray &rhs)
\overload operator>()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4149,12 +4276,11 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
-/*! \fn bool QString::operator>(const char *other) const
+/*! \fn bool QString::operator>(const QString &lhs, const char * const &rhs)
\overload operator>()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
@@ -4162,39 +4288,39 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
for example.
*/
-/*! \fn bool QString::operator>=(const QString &s1, const QString &s2)
+/*! \fn bool QString::operator>=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is lexically greater than or equal to
- string \a s2; otherwise returns \c false.
+ Returns \c true if string \a lhs is lexically greater than or equal to
+ string \a rhs; otherwise returns \c false.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator>=(const QString &s1, QLatin1StringView s2)
+ \fn bool QString::operator>=(const QString &lhs, const QLatin1StringView &rhs)
\overload operator>=()
- Returns \c true if \a s1 is lexically greater than or equal to \a s2;
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
otherwise returns \c false.
*/
/*!
- \fn bool QString::operator>=(QLatin1StringView s1, const QString &s2)
+ \fn bool QString::operator>=(const QLatin1StringView &lhs, const QString &rhs)
\overload operator>=()
- Returns \c true if \a s1 is lexically greater than or equal to \a s2;
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
otherwise returns \c false.
*/
-/*! \fn bool QString::operator>=(const QByteArray &other) const
+/*! \fn bool QString::operator>=(const QString &lhs, const QByteArray &rhs)
\overload operator>=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded in
- the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
@@ -4202,12 +4328,11 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
for example.
*/
-/*! \fn bool QString::operator>=(const char *other) const
+/*! \fn bool QString::operator>=(const QString &lhs, const char * const &rhs)
\overload operator>=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
@@ -4215,29 +4340,29 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
for example.
*/
-/*! \fn bool QString::operator!=(const QString &s1, const QString &s2)
+/*! \fn bool QString::operator!=(const QString &lhs, const QString &rhs)
- Returns \c true if string \a s1 is not equal to string \a s2;
+ Returns \c true if string \a lhs is not equal to string \a rhs;
otherwise returns \c false.
\sa {Comparing Strings}
*/
-/*! \fn bool QString::operator!=(const QString &s1, QLatin1StringView s2)
+/*! \fn bool QString::operator!=(const QString &lhs, const QLatin1StringView &rhs)
- Returns \c true if string \a s1 is not equal to string \a s2.
+ Returns \c true if string \a lhs is not equal to string \a rhs.
Otherwise returns \c false.
\overload operator!=()
*/
-/*! \fn bool QString::operator!=(const QByteArray &other) const
+/*! \fn bool QString::operator!=(const QString &lhs, const QByteArray &rhs)
\overload operator!=()
- The \a other byte array is converted to a QString using the
- fromUtf8() function. If any NUL characters ('\\0') are embedded
- in the byte array, they will be included in the transformation.
+ The \a rhs byte array is converted to a QUtf8StringView.
+ If any NUL characters ('\\0') are embedded in the byte array, they will be
+ included in the transformation.
You can disable this operator by defining \l QT_NO_CAST_FROM_ASCII
when you compile your applications. This can be useful if you want
@@ -4245,12 +4370,11 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
for example.
*/
-/*! \fn bool QString::operator!=(const char *other) const
+/*! \fn bool QString::operator!=(const QString &lhs, const char * const &rhs)
\overload operator!=()
- The \a other const char pointer is converted to a QString using
- the fromUtf8() function.
+ The \a rhs const char pointer is converted to a QUtf8StringView.
You can disable this operator by defining
\l QT_NO_CAST_FROM_ASCII when you compile your applications. This
@@ -4258,6 +4382,90 @@ QString &QString::replace(QChar c, QLatin1StringView after, Qt::CaseSensitivity
go through QObject::tr(), for example.
*/
+/*! \fn bool QString::operator==(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is equal to the UTF-8 encoding of
+ \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator!=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is not equal to the UTF-8 encoding of
+ \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator<(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically less than the UTF-8 encoding
+ of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator>(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically greater than the UTF-8
+ encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator<=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is lexically less than or equal to the
+ UTF-8 encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
+/*! \fn bool QString::operator>=(const QByteArray &lhs, const QString &rhs)
+
+ Returns \c true if byte array \a lhs is greater than or equal to the UTF-8
+ encoding of \a rhs; otherwise returns \c false.
+
+ The comparison is case sensitive.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications. You
+ then need to call QString::fromUtf8(), QString::fromLatin1(),
+ or QString::fromLocal8Bit() explicitly if you want to convert the byte
+ array to a QString before doing the comparison.
+*/
+
/*!
\include qstring.qdocinc {qstring-first-index-of} {string} {str}
@@ -4312,14 +4520,11 @@ qsizetype QString::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensit
}
/*!
+ \fn qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
\overload indexOf()
\include qstring.qdocinc {qstring-first-index-of} {character} {ch}
*/
-qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
-{
- return qFindChar(QStringView(unicode(), size()), ch, from, cs);
-}
/*!
\include qstring.qdocinc {qstring-last-index-of} {string} {str}
@@ -4414,14 +4619,11 @@ qsizetype QString::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSe
*/
/*!
+ \fn qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
\overload lastIndexOf()
\include qstring.qdocinc {qstring-last-index-of} {character} {ch}
*/
-qsizetype QString::lastIndexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
-{
- return qLastIndexOf(QStringView(*this), ch, from, cs);
-}
/*!
\fn QString::lastIndexOf(QChar ch, Qt::CaseSensitivity) const
@@ -4510,7 +4712,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
// 1. build the backreferences list, holding where the backreferences
// are in the replacement string
- QList<QStringCapture> backReferences;
+ QVarLengthArray<QStringCapture> backReferences;
const qsizetype al = after.size();
const QChar *ac = after.unicode();
@@ -4542,7 +4744,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
qsizetype newLength = 0; // length of the new string, with all the replacements
qsizetype lastEnd = 0;
- QList<QStringView> chunks;
+ QVarLengthArray<QStringView> chunks;
const QStringView copyView{ copy }, afterView{ after };
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
@@ -4941,7 +5143,7 @@ public:
};
Q_DECLARE_TYPEINFO(qt_section_chunk, Q_RELOCATABLE_TYPE);
-static QString extractSections(const QList<qt_section_chunk> &sections, qsizetype start, qsizetype end,
+static QString extractSections(QSpan<qt_section_chunk> sections, qsizetype start, qsizetype end,
QString::SectionFlags flags)
{
const qsizetype sectionsSize = sections.size();
@@ -4954,7 +5156,7 @@ static QString extractSections(const QList<qt_section_chunk> &sections, qsizetyp
} else {
qsizetype skip = 0;
for (qsizetype k = 0; k < sectionsSize; ++k) {
- const qt_section_chunk &section = sections.at(k);
+ const qt_section_chunk &section = sections[k];
if (section.length == section.string.size())
skip++;
}
@@ -4970,7 +5172,7 @@ static QString extractSections(const QList<qt_section_chunk> &sections, qsizetyp
qsizetype x = 0;
qsizetype first_i = start, last_i = end;
for (qsizetype i = 0; x <= end && i < sectionsSize; ++i) {
- const qt_section_chunk &section = sections.at(i);
+ const qt_section_chunk &section = sections[i];
const bool empty = (section.length == section.string.size());
if (x >= start) {
if (x == start)
@@ -4987,13 +5189,13 @@ static QString extractSections(const QList<qt_section_chunk> &sections, qsizetyp
}
if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) {
- const qt_section_chunk &section = sections.at(first_i);
+ const qt_section_chunk &section = sections[first_i];
ret.prepend(section.string.left(section.length));
}
if ((flags & QString::SectionIncludeTrailingSep)
&& last_i < sectionsSize - 1) {
- const qt_section_chunk &section = sections.at(last_i+1);
+ const qt_section_chunk &section = sections[last_i + 1];
ret += section.string.left(section.length);
}
@@ -5029,7 +5231,7 @@ QString QString::section(const QRegularExpression &re, qsizetype start, qsizetyp
if (flags & SectionCaseInsensitiveSeps)
sep.setPatternOptions(sep.patternOptions() | QRegularExpression::CaseInsensitiveOption);
- QList<qt_section_chunk> sections;
+ QVarLengthArray<qt_section_chunk> sections;
qsizetype n = size(), m = 0, last_m = 0, last_len = 0;
QRegularExpressionMatchIterator iterator = sep.globalMatch(*this);
while (iterator.hasNext()) {
@@ -5046,6 +5248,9 @@ QString QString::section(const QRegularExpression &re, qsizetype start, qsizetyp
#endif // QT_CONFIG(regularexpression)
/*!
+ \fn QString QString::left(qsizetype n) const &
+ \fn QString QString::left(qsizetype n) &&
+
Returns a substring that contains the \a n leftmost characters
of the string.
@@ -5057,14 +5262,11 @@ QString QString::section(const QRegularExpression &re, qsizetype start, qsizetyp
\sa first(), last(), startsWith(), chopped(), chop(), truncate()
*/
-QString QString::left(qsizetype n) const
-{
- if (size_t(n) >= size_t(size()))
- return *this;
- return QString((const QChar*) d.data(), n);
-}
/*!
+ \fn QString QString::right(qsizetype n) const &
+ \fn QString QString::right(qsizetype n) &&
+
Returns a substring that contains the \a n rightmost characters
of the string.
@@ -5074,16 +5276,13 @@ QString QString::left(qsizetype n) const
The entire string is returned if \a n is greater than or equal
to size(), or less than zero.
- \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate()
+ \sa endsWith(), last(), first(), sliced(), chopped(), chop(), truncate(), slice()
*/
-QString QString::right(qsizetype n) const
-{
- if (size_t(n) >= size_t(size()))
- return *this;
- return QString(constData() + size() - n, n);
-}
/*!
+ \fn QString QString::mid(qsizetype position, qsizetype n) const &
+ \fn QString QString::mid(qsizetype position, qsizetype n) &&
+
Returns a string that contains \a n characters of this string,
starting at the specified \a position index.
@@ -5096,11 +5295,9 @@ QString QString::right(qsizetype n) const
\a n is -1 (default), the function returns all characters that
are available from the specified \a position.
-
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), sliced(), chopped(), chop(), truncate(), slice()
*/
-
-QString QString::mid(qsizetype position, qsizetype n) const
+QString QString::mid(qsizetype position, qsizetype n) const &
{
qsizetype p = position;
qsizetype l = n;
@@ -5113,13 +5310,33 @@ QString QString::mid(qsizetype position, qsizetype n) const
case QContainerImplHelper::Full:
return *this;
case QContainerImplHelper::Subset:
- return QString(constData() + p, l);
+ return sliced(p, l);
+ }
+ Q_UNREACHABLE_RETURN(QString());
+}
+
+QString QString::mid(qsizetype position, qsizetype n) &&
+{
+ qsizetype p = position;
+ qsizetype l = n;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(size(), &p, &l)) {
+ case QContainerImplHelper::Null:
+ return QString();
+ case QContainerImplHelper::Empty:
+ resize(0); // keep capacity if we've reserve()d
+ [[fallthrough]];
+ case QContainerImplHelper::Full:
+ return std::move(*this);
+ case QContainerImplHelper::Subset:
+ return std::move(*this).sliced(p, l);
}
Q_UNREACHABLE_RETURN(QString());
}
/*!
- \fn QString QString::first(qsizetype n) const
+ \fn QString QString::first(qsizetype n) const &
+ \fn QString QString::first(qsizetype n) &&
\since 6.0
Returns a string that contains the first \a n characters
@@ -5129,11 +5346,12 @@ QString QString::mid(qsizetype position, qsizetype n) const
\snippet qstring/main.cpp 31
- \sa last(), sliced(), startsWith(), chopped(), chop(), truncate()
+ \sa last(), sliced(), startsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QString QString::last(qsizetype n) const
+ \fn QString QString::last(qsizetype n) const &
+ \fn QString QString::last(qsizetype n) &&
\since 6.0
Returns the string that contains the last \a n characters of this string.
@@ -5142,11 +5360,12 @@ QString QString::mid(qsizetype position, qsizetype n) const
\snippet qstring/main.cpp 48
- \sa first(), sliced(), endsWith(), chopped(), chop(), truncate()
+ \sa first(), sliced(), endsWith(), chopped(), chop(), truncate(), slice()
*/
/*!
- \fn QString QString::sliced(qsizetype pos, qsizetype n) const
+ \fn QString QString::sliced(qsizetype pos, qsizetype n) const &
+ \fn QString QString::sliced(qsizetype pos, qsizetype n) &&
\since 6.0
Returns a string that contains \a n characters of this string,
@@ -5157,11 +5376,20 @@ QString QString::mid(qsizetype position, qsizetype n) const
\snippet qstring/main.cpp 34
- \sa first(), last(), chopped(), chop(), truncate()
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
*/
+QString QString::sliced_helper(QString &str, qsizetype pos, qsizetype n)
+{
+ if (n == 0)
+ return QString(DataPointer::fromRawData(&_empty, 0));
+ DataPointer d = std::move(str.d).sliced(pos, n);
+ d.data()[n] = 0;
+ return QString(std::move(d));
+}
/*!
- \fn QString QString::sliced(qsizetype pos) const
+ \fn QString QString::sliced(qsizetype pos) const &
+ \fn QString QString::sliced(qsizetype pos) &&
\since 6.0
\overload
@@ -5170,11 +5398,40 @@ QString QString::mid(qsizetype position, qsizetype n) const
\note The behavior is undefined when \a pos < 0 or \a pos > size().
- \sa first(), last(), sliced(), chopped(), chop(), truncate()
+ \sa first(), last(), chopped(), chop(), truncate(), slice()
+*/
+
+/*!
+ \fn QString &QString::slice(qsizetype pos, qsizetype n)
+ \since 6.8
+
+ Modifies this string to start at position \a pos, extending for \a n
+ characters (code points), and returns a reference to this string.
+
+ \note The behavior is undefined if \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+
+ \snippet qstring/main.cpp 86
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QString &QString::slice(qsizetype pos)
+ \since 6.8
+ \overload
+
+ Modifies this string to start at position \a pos and extending to its end,
+ and returns a reference to this string.
+
+ \note The behavior is undefined if \a pos < 0 or \a pos > size().
+
+ \sa sliced(), first(), last(), chopped(), chop(), truncate()
*/
/*!
- \fn QString QString::chopped(qsizetype len) const
+ \fn QString QString::chopped(qsizetype len) const &
+ \fn QString QString::chopped(qsizetype len) &&
\since 5.10
Returns a string that contains the size() - \a len leftmost characters
@@ -5182,7 +5439,7 @@ QString QString::mid(qsizetype position, qsizetype n) const
\note The behavior is undefined if \a len is negative or greater than size().
- \sa endsWith(), first(), last(), sliced(), chop(), truncate()
+ \sa endsWith(), first(), last(), sliced(), chop(), truncate(), slice()
*/
/*!
@@ -5286,6 +5543,27 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
return foldCase(at(size() - 1)) == foldCase(c);
}
+static bool checkCase(QStringView s, QUnicodeTables::Case c) noexcept
+{
+ QStringIterator it(s);
+ while (it.hasNext()) {
+ const char32_t uc = it.next();
+ if (qGetProp(uc)->cases[c].diff)
+ return false;
+ }
+ return true;
+}
+
+bool QtPrivate::isLower(QStringView s) noexcept
+{
+ return checkCase(s, QUnicodeTables::LowerCase);
+}
+
+bool QtPrivate::isUpper(QStringView s) noexcept
+{
+ return checkCase(s, QUnicodeTables::UpperCase);
+}
+
/*!
Returns \c true if the string is uppercase, that is, it's identical
to its toUpper() folding.
@@ -5301,15 +5579,7 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
*/
bool QString::isUpper() const
{
- QStringIterator it(*this);
-
- while (it.hasNext()) {
- const char32_t uc = it.next();
- if (qGetProp(uc)->cases[QUnicodeTables::UpperCase].diff)
- return false;
- }
-
- return true;
+ return QtPrivate::isUpper(qToStringViewIgnoringNull(*this));
}
/*!
@@ -5327,15 +5597,7 @@ bool QString::isUpper() const
*/
bool QString::isLower() const
{
- QStringIterator it(*this);
-
- while (it.hasNext()) {
- const char32_t uc = it.next();
- if (qGetProp(uc)->cases[QUnicodeTables::LowerCase].diff)
- return false;
- }
-
- return true;
+ return QtPrivate::isLower(qToStringViewIgnoringNull(*this));
}
static QByteArray qt_convert_to_latin1(QStringView string);
@@ -5614,7 +5876,7 @@ QString QString::fromLatin1(QByteArrayView ba)
} else if (ba.size() == 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
- d = DataPointer(Data::allocate(ba.size()), ba.size());
+ d = DataPointer(ba.size(), ba.size());
Q_CHECK_PTR(d.data());
d.data()[ba.size()] = '\0';
char16_t *dst = d.data();
@@ -5762,6 +6024,7 @@ QString QString::fromUtf8(QByteArrayView ba)
return QUtf8::convertToUnicode(ba);
}
+#ifndef QT_BOOTSTRAPPED
/*!
\since 5.3
Returns a QString initialized with the first \a size characters
@@ -5823,7 +6086,7 @@ QString QString::fromUcs4(const char32_t *unicode, qsizetype size)
QStringDecoder toUtf16(QStringDecoder::Utf32, QStringDecoder::Flag::Stateless);
return toUtf16(QByteArrayView(reinterpret_cast<const char *>(unicode), size * 4));
}
-
+#endif // !QT_BOOTSTRAPPED
/*!
Resizes the string to \a size characters and copies \a unicode
@@ -5888,9 +6151,7 @@ namespace {
template <typename StringView>
StringView qt_trimmed(StringView s) noexcept
{
- auto begin = s.begin();
- auto end = s.end();
- QStringAlgorithms<const StringView>::trimmed_helper_positions(begin, end);
+ const auto [begin, end] = QStringAlgorithms<const StringView>::trimmed_helper_positions(s);
return StringView{begin, end};
}
}
@@ -6097,11 +6358,8 @@ void QString::chop(qsizetype n)
QString& QString::fill(QChar ch, qsizetype size)
{
resize(size < 0 ? d.size : size);
- if (d.size) {
- QChar *i = (QChar*)d.data() + d.size;
- QChar *b = (QChar*)d.data();
- std::fill(b, i, ch);
- }
+ if (d.size)
+ std::fill(d.data(), d.data() + d.size, ch.unicode());
return *this;
}
@@ -6127,6 +6385,16 @@ QString& QString::fill(QChar ch, qsizetype size)
\sa isEmpty(), resize()
*/
+/*!
+ \fn qsizetype QString::max_size()
+ \since 6.8
+
+ This function is provided for STL compatibility.
+ It returns the maximum number of elements that the string can
+ theoretically hold. In practice, the number can be much smaller,
+ limited by the amount of memory available to the system.
+*/
+
/*! \fn bool QString::isNull() const
Returns \c true if this string is null; otherwise returns \c false.
@@ -6229,61 +6497,61 @@ QString& QString::fill(QChar ch, qsizetype size)
*/
/*!
- \fn bool QString::operator==(const char *s1, const QString &s2)
+ \fn bool QString::operator==(const char * const &lhs, const QString &rhs)
\overload operator==()
- Returns \c true if \a s1 is equal to \a s2; otherwise returns \c false.
- Note that no string is equal to \a s1 being 0.
+ Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
+ Note that no string is equal to \a lhs being 0.
- Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}.
+ Equivalent to \c {lhs != 0 && compare(lhs, rhs) == 0}.
*/
/*!
- \fn bool QString::operator!=(const char *s1, const QString &s2)
+ \fn bool QString::operator!=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is not equal to \a s2; otherwise returns
+ Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
\c false.
- For \a s1 != 0, this is equivalent to \c {compare(} \a s1, \a s2
- \c {) != 0}. Note that no string is equal to \a s1 being 0.
+ For \a lhs != 0, this is equivalent to \c {compare(} \a lhs, \a rhs
+ \c {) != 0}. Note that no string is equal to \a lhs being 0.
*/
/*!
- \fn bool QString::operator<(const char *s1, const QString &s2)
+ \fn bool QString::operator<(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically less than \a s2; otherwise
- returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) < 0}.
+ Returns \c true if \a lhs is lexically less than \a rhs; otherwise
+ returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) < 0}.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator<=(const char *s1, const QString &s2)
+ \fn bool QString::operator<=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically less than or equal to \a s2;
- otherwise returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) <= 0}.
+ Returns \c true if \a lhs is lexically less than or equal to \a rhs;
+ otherwise returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) <= 0}.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator>(const char *s1, const QString &s2)
+ \fn bool QString::operator>(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically greater than \a s2; otherwise
- returns \c false. Equivalent to \c {compare(s1, s2) > 0}.
+ Returns \c true if \a lhs is lexically greater than \a rhs; otherwise
+ returns \c false. Equivalent to \c {compare(lhs, rhs) > 0}.
\sa {Comparing Strings}
*/
/*!
- \fn bool QString::operator>=(const char *s1, const QString &s2)
+ \fn bool QString::operator>=(const char * const &lhs, const QString &rhs)
- Returns \c true if \a s1 is lexically greater than or equal to \a s2;
- otherwise returns \c false. For \a s1 != 0, this is equivalent to \c
- {compare(s1, s2) >= 0}.
+ Returns \c true if \a lhs is lexically greater than or equal to \a rhs;
+ otherwise returns \c false. For \a lhs != 0, this is equivalent to \c
+ {compare(lhs, rhs) >= 0}.
\sa {Comparing Strings}
*/
@@ -6323,9 +6591,9 @@ QString& QString::fill(QChar ch, qsizetype size)
\fn int QString::compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
\since 4.2
- Compares \a s1 with \a s2 and returns an integer less than, equal
- to, or greater than zero if \a s1 is less than, equal to, or
- greater than \a s2.
+ Compares the string \a s1 with the string \a s2 and returns a negative integer
+ if \a s1 is less than \a s2, a positive integer if it is greater than \a s2,
+ and zero if they are equal.
\include qstring.qdocinc {search-comparison-case-sensitivity} {comparison}
@@ -6387,10 +6655,9 @@ QString& QString::fill(QChar ch, qsizetype size)
\overload compare()
\since 4.2
- Lexically compares this string with the \a other string and
- returns an integer less than, equal to, or greater than zero if
- this string is less than, equal to, or greater than the other
- string.
+ Lexically compares this string with the string \a other and returns
+ a negative integer if this string is less than \a other, a positive
+ integer if it is greater than \a other, and zero if they are equal.
Same as compare(*this, \a other, \a cs).
*/
@@ -6451,6 +6718,110 @@ int QString::compare_helper(const QChar *data1, qsizetype length1, const char *d
\overload compare()
*/
+bool comparesEqual(const QByteArrayView &lhs, const QChar &rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArrayView &lhs, const QChar &rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArrayView &lhs, char16_t rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArrayView &lhs, char16_t rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArray &lhs, const QChar &rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArray &lhs, const QChar &rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+bool comparesEqual(const QByteArray &lhs, char16_t rhs) noexcept
+{
+ return QtPrivate::equalStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+}
+
+Qt::strong_ordering compareThreeWay(const QByteArray &lhs, char16_t rhs) noexcept
+{
+ const int res = QtPrivate::compareStrings(QUtf8StringView(lhs), QStringView(&rhs, 1));
+ return Qt::compareThreeWay(res, 0);
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QT_FASTCALL QChar::equal_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::equalStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+int QT_FASTCALL QChar::compare_helper(QChar lhs, const char *rhs) noexcept
+{
+ return QtPrivate::compareStrings(QStringView(&lhs, 1), QUtf8StringView(rhs));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QStringView::equal_helper(QStringView sv, const char *data, qsizetype len)
+{
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(data || len == 0);
+ return QtPrivate::equalStrings(sv, QUtf8StringView(data, len));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+int QStringView::compare_helper(QStringView sv, const char *data, qsizetype len)
+{
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(data || len == 0);
+ return QtPrivate::compareStrings(sv, QUtf8StringView(data, len));
+}
+
+/*!
+ \internal
+ \since 6.8
+*/
+bool QLatin1StringView::equal_helper(QLatin1StringView s1, const char *s2, qsizetype len) noexcept
+{
+ // because qlatin1stringview.h can't include qutf8stringview.h
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(s2 || len == 0);
+ return QtPrivate::equalStrings(s1, QUtf8StringView(s2, len));
+}
+
+/*!
+ \internal
+ \since 6.6
+*/
+int QLatin1StringView::compare_helper(const QLatin1StringView &s1, const char *s2, qsizetype len) noexcept
+{
+ // because qlatin1stringview.h can't include qutf8stringview.h
+ Q_ASSERT(len >= 0);
+ Q_ASSERT(s2 || len == 0);
+ return QtPrivate::compareStrings(s1, QUtf8StringView(s2, len));
+}
+
/*!
\internal
\since 4.5
@@ -7275,10 +7646,14 @@ static Int toIntegral(QStringView string, bool *ok, int base)
QVarLengthArray<uchar> latin1(string.size());
qt_to_latin1(latin1.data(), string.utf16(), string.size());
+ QSimpleParsedNumber<Int> r;
if constexpr (std::is_signed_v<Int>)
- return QLocaleData::bytearrayToLongLong(latin1, base, ok);
+ r = QLocaleData::bytearrayToLongLong(latin1, base);
else
- return QLocaleData::bytearrayToUnsLongLong(latin1, base, ok);
+ r = QLocaleData::bytearrayToUnsLongLong(latin1, base);
+ if (ok)
+ *ok = r.ok();
+ return r.result;
}
qlonglong QString::toIntegral_helper(QStringView string, bool *ok, int base)
@@ -7953,6 +8328,7 @@ QStringList QString::split(const QRegularExpression &re, Qt::SplitBehavior behav
}
/*!
+ \overload
\since 6.0
Splits the string into substring views wherever the regular expression \a re
@@ -8103,7 +8479,7 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi
return copy;
}
-#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
static void checkArgEscape(QStringView s)
{
// If we're in here, it means that qArgDigitValue has accepted the
@@ -8177,7 +8553,7 @@ static ArgEscapeData findArgEscapes(QStringView s)
// ### Qt 7: do not allow anything but ASCII digits
// in arg()'s replacements.
-#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
const QChar *escapeBegin = c;
const QChar *escapeEnd = escapeBegin + 1;
#endif
@@ -8189,13 +8565,13 @@ static ArgEscapeData findArgEscapes(QStringView s)
if (next_escape != -1) {
escape = (10 * escape) + next_escape;
++c;
-#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
++escapeEnd;
#endif
}
}
-#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
+#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
checkArgEscape(QStringView(escapeBegin, escapeEnd));
#endif
@@ -8275,7 +8651,8 @@ static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, qsizetyp
rc = std::fill_n(rc, pad_chars, fillChar);
}
- memcpy(rc, use.data(), use.size() * sizeof(QChar));
+ if (use.size())
+ memcpy(rc, use.data(), use.size() * sizeof(QChar));
rc += use.size();
if (field_width < 0) { // right padded
@@ -8507,8 +8884,7 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) cons
QString arg;
if (d.occurrences > d.locale_occurrences) {
arg = QLocaleData::c()->longLongToString(a, -1, base, fieldWidth, flags);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
- || fieldWidth <= arg.size());
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= arg.size());
}
QString localeArg;
@@ -8517,8 +8893,7 @@ QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) cons
if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
flags |= QLocaleData::GroupDigits;
localeArg = locale.d->m_data->longLongToString(a, -1, base, fieldWidth, flags);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
- || fieldWidth <= localeArg.size());
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= localeArg.size());
}
return replaceArgEscapes(*this, d, fieldWidth, arg, localeArg, fillChar);
@@ -8555,8 +8930,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) con
QString arg;
if (d.occurrences > d.locale_occurrences) {
arg = QLocaleData::c()->unsLongLongToString(a, -1, base, fieldWidth, flags);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
- || fieldWidth <= arg.size());
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= arg.size());
}
QString localeArg;
@@ -8565,8 +8939,7 @@ QString QString::arg(qulonglong a, int fieldWidth, int base, QChar fillChar) con
if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
flags |= QLocaleData::GroupDigits;
localeArg = locale.d->m_data->unsLongLongToString(a, -1, base, fieldWidth, flags);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
- || fieldWidth <= localeArg.size());
+ Q_ASSERT(fillChar != u'0' || fieldWidth <= localeArg.size());
}
return replaceArgEscapes(*this, d, fieldWidth, arg, localeArg, fillChar);
@@ -8677,7 +9050,7 @@ QString QString::arg(double a, int fieldWidth, char format, int precision, QChar
if (d.occurrences > d.locale_occurrences) {
arg = QLocaleData::c()->doubleToString(a, precision, form, fieldWidth,
flags | QLocaleData::ZeroPadExponent);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
+ Q_ASSERT(fillChar != u'0' || !qt_is_finite(a)
|| fieldWidth <= arg.size());
}
@@ -8693,7 +9066,7 @@ QString QString::arg(double a, int fieldWidth, char format, int precision, QChar
if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
flags |= QLocaleData::AddTrailingZeroes;
localeArg = locale.d->m_data->doubleToString(a, precision, form, fieldWidth, flags);
- Q_ASSERT(fillChar != u'0' || !qIsFinite(a)
+ Q_ASSERT(fillChar != u'0' || !qt_is_finite(a)
|| fieldWidth <= localeArg.size());
}
@@ -8704,7 +9077,7 @@ static inline char16_t to_unicode(const QChar c) { return c.unicode(); }
static inline char16_t to_unicode(const char c) { return QLatin1Char{c}.unicode(); }
template <typename Char>
-static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999)
+static int getEscape(const Char *uc, qsizetype *pos, qsizetype len)
{
qsizetype i = *pos;
++i;
@@ -8715,17 +9088,16 @@ static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumbe
if (uint(escape) >= 10U)
return -1;
++i;
- while (i < len) {
+ if (i < len) {
+ // there's a second digit
int digit = to_unicode(uc[i]) - '0';
- if (uint(digit) >= 10U)
- break;
- escape = (escape * 10) + digit;
- ++i;
- }
- if (escape <= maxNumber) {
- *pos = i;
- return escape;
+ if (uint(digit) < 10U) {
+ escape = (escape * 10) + digit;
+ ++i;
+ }
}
+ *pos = i;
+ return escape;
}
return -1;
}
@@ -8926,26 +9298,6 @@ QString QtPrivate::argToQString(QLatin1StringView pattern, size_t n, const ArgBa
return argToQStringImpl(pattern, n, args);
}
-/*! \fn bool QString::isSimpleText() const
-
- \internal
-*/
-bool QString::isSimpleText() const
-{
- const char16_t *p = d.data();
- const char16_t * const end = p + d.size;
- while (p < end) {
- char16_t uc = *p;
- // sort out regions of complex text formatting
- if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) {
- return false;
- }
- p++;
- }
-
- return true;
-}
-
/*! \fn bool QString::isRightToLeft() const
Returns \c true if the string is read right to left.
@@ -9067,6 +9419,7 @@ QString::iterator QString::erase(QString::const_iterator first, QString::const_i
/*!
\fn QString::iterator QString::erase(QString::const_iterator it)
+ \overload
\since 6.5
Removes the character denoted by \c it from the string.
@@ -9192,7 +9545,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\sa toUcs4(), toStdWString(), toStdU16String()
*/
-#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+#if !defined(QT_NO_DATASTREAM)
/*!
\fn QDataStream &operator<<(QDataStream &stream, const QString &string)
\relates QString
@@ -9210,16 +9563,15 @@ QDataStream &operator<<(QDataStream &out, const QString &str)
if (!str.isNull() || out.version() < 3) {
if ((out.byteOrder() == QDataStream::BigEndian) == (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
out.writeBytes(reinterpret_cast<const char *>(str.unicode()),
- static_cast<uint>(sizeof(QChar) * str.size()));
+ static_cast<qsizetype>(sizeof(QChar) * str.size()));
} else {
QVarLengthArray<char16_t> buffer(str.size());
qbswap<sizeof(char16_t)>(str.constData(), str.size(), buffer.data());
out.writeBytes(reinterpret_cast<const char *>(buffer.data()),
- static_cast<uint>(sizeof(char16_t) * buffer.size()));
+ static_cast<qsizetype>(sizeof(char16_t) * buffer.size()));
}
} else {
- // write null marker
- out << (quint32)0xffffffff;
+ QDataStream::writeQSizeType(out, -1); // write null marker
}
}
return out;
@@ -9241,20 +9593,25 @@ QDataStream &operator>>(QDataStream &in, QString &str)
in >> l;
str = QString::fromLatin1(l);
} else {
- quint32 bytes = 0;
- in >> bytes; // read size of string
- if (bytes == 0xffffffff) { // null string
+ qint64 size = QDataStream::readQSizeType(in);
+ qsizetype bytes = size;
+ if (size != bytes || size < -1) {
str.clear();
- } else if (bytes > 0) { // not empty
+ in.setStatus(QDataStream::SizeLimitExceeded);
+ return in;
+ }
+ if (bytes == -1) { // null string
+ str = QString();
+ } else if (bytes > 0) {
if (bytes & 0x1) {
str.clear();
in.setStatus(QDataStream::ReadCorruptData);
return in;
}
- const quint32 Step = 1024 * 1024;
- quint32 len = bytes / 2;
- quint32 allocated = 0;
+ const qsizetype Step = 1024 * 1024;
+ qsizetype len = bytes / 2;
+ qsizetype allocated = 0;
while (allocated < len) {
int blockSize = qMin(Step, len - allocated);
@@ -9519,6 +9876,8 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
{
const qsizetype l = haystack0.size();
const qsizetype sl = needle0.size();
+ if (sl == 1)
+ return findString(haystack0, from, needle0[0], cs);
if (from < 0)
from += l;
if (std::size_t(sl + from) > std::size_t(l))
@@ -9528,9 +9887,6 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
if (!l)
return -1;
- if (sl == 1)
- return qFindChar(haystack0, needle0[0], from, cs);
-
/*
We use the Boyer-Moore algorithm in cases where the overhead
for the skip table should pay off, otherwise we use a simple
@@ -9632,7 +9988,7 @@ qsizetype QtPrivate::findString(QLatin1StringView haystack, qsizetype from, QLat
if (cs == Qt::CaseSensitive) {
if (needle.size() == 1) {
- Q_ASSUME(haystack.data() != nullptr); // see size check above
+ Q_ASSERT(haystack.data() != nullptr); // see size check above
if (auto it = memchr(haystack.data() + from, needle.front().toLatin1(), adjustedSize))
return static_cast<const char *>(it) - haystack.data();
return -1;
@@ -9661,7 +10017,7 @@ qsizetype QtPrivate::findString(QLatin1StringView haystack, qsizetype from, QLat
const auto end = haystack.end() - needle.size() + 1;
auto ciMatch = CaseInsensitiveL1::matcher(needle[0].toLatin1());
const qsizetype nlen1 = needle.size() - 1;
- for (auto it = std::find_if(begin + from, end, ciMatch); it < end;
+ for (auto it = std::find_if(begin + from, end, ciMatch); it != end;
it = std::find_if(it + 1, end, ciMatch)) {
// In this comparison we skip the first character because we know it's a match
if (!nlen1 || QLatin1StringView(it + 1, nlen1).compare(needle.sliced(1), cs) == 0)
@@ -9674,6 +10030,11 @@ qsizetype QtPrivate::findString(QLatin1StringView haystack, qsizetype from, QLat
return matcher.indexIn(haystack, from);
}
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, char16_t needle, Qt::CaseSensitivity cs) noexcept
+{
+ return qLastIndexOf(haystack, QChar(needle), from, cs);
+}
+
qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qLastIndexOf(haystack, from, needle, cs);
@@ -9812,10 +10173,14 @@ qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re)
*/
QString QString::toHtmlEscaped() const
{
+ const auto pos = std::u16string_view(*this).find_first_of(u"<>&\"");
+ if (pos == std::u16string_view::npos)
+ return *this;
QString rich;
const qsizetype len = size();
rich.reserve(qsizetype(len * 1.1));
- for (QChar ch : *this) {
+ rich += qToStringViewIgnoringNull(*this).first(pos);
+ for (auto ch : qToStringViewIgnoringNull(*this).sliced(pos)) {
if (ch == u'<')
rich += "&lt;"_L1;
else if (ch == u'>')
@@ -10020,5 +10385,4 @@ void QAbstractConcatenable::appendLatin1To(QLatin1StringView in, QChar *out) noe
QT_END_NAMESPACE
-#undef IS_RAW_DATA
#undef REHASH