summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qanystringview.h21
-rw-r--r--src/corelib/text/qbytearray.cpp116
-rw-r--r--src/corelib/text/qbytearray.h6
-rw-r--r--src/corelib/text/qbytearrayalgorithms.h6
-rw-r--r--src/corelib/text/qbytearraymatcher.cpp71
-rw-r--r--src/corelib/text/qbytearrayview.h15
-rw-r--r--src/corelib/text/qchar.cpp51
-rw-r--r--src/corelib/text/qchar.h14
-rw-r--r--src/corelib/text/qlatin1stringmatcher.cpp42
-rw-r--r--src/corelib/text/qlatin1stringmatcher.h9
-rw-r--r--src/corelib/text/qlocale.cpp5
-rw-r--r--src/corelib/text/qlocale.h7
-rw-r--r--src/corelib/text/qlocale.qdoc1
-rw-r--r--src/corelib/text/qlocale_tools.cpp87
-rw-r--r--src/corelib/text/qlocale_tools_p.h21
-rw-r--r--src/corelib/text/qregularexpression.cpp17
-rw-r--r--src/corelib/text/qregularexpression.h34
-rw-r--r--src/corelib/text/qstaticlatin1stringmatcher.h23
-rw-r--r--src/corelib/text/qstaticlatin1stringmatcher.qdoc1
-rw-r--r--src/corelib/text/qstring.cpp105
-rw-r--r--src/corelib/text/qstring.h6
-rw-r--r--src/corelib/text/qstringalgorithms.h1
-rw-r--r--src/corelib/text/qstringconverter.cpp64
-rw-r--r--src/corelib/text/qstringconverter.h10
-rw-r--r--src/corelib/text/qstringconverter_base.h7
-rw-r--r--src/corelib/text/qstringconverter_p.h1
-rw-r--r--src/corelib/text/qutf8stringview.h3
27 files changed, 427 insertions, 317 deletions
diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h
index 01efd83743..843fa7e5c9 100644
--- a/src/corelib/text/qanystringview.h
+++ b/src/corelib/text/qanystringview.h
@@ -62,10 +62,13 @@ private:
};
template <typename Char>
- using if_compatible_char = std::enable_if_t<std::disjunction_v<
+ using is_compatible_char = std::disjunction<
QtPrivate::IsCompatibleCharType<Char>,
QtPrivate::IsCompatibleChar8Type<Char>
- >, bool>;
+ >;
+
+ template <typename Char>
+ using if_compatible_char = std::enable_if_t<is_compatible_char<Char>::value, bool>;
template <typename Pointer>
using if_compatible_pointer = std::enable_if_t<std::disjunction_v<
@@ -87,6 +90,7 @@ private:
std::is_same<q20::remove_cvref_t<T>, QAnyStringView::Tag>,
std::is_same<q20::remove_cvref_t<T>, QAnyStringView>, // don't make a copy/move ctor
std::is_pointer<std::decay_t<T>>, // const char*, etc
+ is_compatible_char<T>, // don't create a QString/QByteArray, we have a ctor
std::is_same<q20::remove_cvref_t<T>, QByteArray>,
std::is_same<q20::remove_cvref_t<T>, QString>
>>,
@@ -144,6 +148,11 @@ private:
static QChar toQChar(QChar ch) noexcept { return ch; }
static QChar toQChar(QLatin1Char ch) noexcept { return ch; }
+ struct QCharContainer { // private, so users can't pass their own
+ explicit QCharContainer() = default;
+ QChar ch;
+ };
+
explicit constexpr QAnyStringView(const void *d, qsizetype n, std::size_t sizeAndType) noexcept
: m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {}
public:
@@ -193,16 +202,16 @@ public:
constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {})
//noexcept(std::is_nothrow_constructible_v<QByteArray, Container>)
: QAnyStringView(capacity = std::forward<Container>(c)) {}
-
template <typename Char, if_compatible_char<Char> = true>
constexpr QAnyStringView(const Char &c) noexcept
: QAnyStringView{&c, 1} {}
- constexpr QAnyStringView(const QChar &c) noexcept
- : QAnyStringView{&c, 1} {}
+ template <typename Char, if_convertible_to<QChar, Char> = true>
+ constexpr QAnyStringView(Char ch, QCharContainer &&capacity = QCharContainer()) noexcept
+ : QAnyStringView{&(capacity.ch = ch), 1} {}
template <typename Char, typename Container = decltype(QChar::fromUcs4(U'x')),
std::enable_if_t<std::is_same_v<Char, char32_t>, bool> = true>
- constexpr QAnyStringView(Char c, Container &&capacity = {})
+ constexpr QAnyStringView(Char c, Container &&capacity = {}) noexcept
: QAnyStringView(capacity = QChar::fromUcs4(c)) {}
constexpr QAnyStringView(QStringView v) noexcept
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index e6387e4bed..d9f0ee405a 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -56,15 +56,35 @@ static constexpr inline uchar asciiLower(uchar c)
return c >= 'A' && c <= 'Z' ? c | 0x20 : c;
}
-qsizetype qFindByteArray(
- const char *haystack0, qsizetype haystackLen, qsizetype from,
- const char *needle0, qsizetype needleLen);
-
/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
/*! \relates QByteArray
+ \internal
+
+ Wrapper around memrchr() for systems that don't have it. It's provided in
+ every system because, as a GNU extension, memrchr() may not be declared in
+ string.h depending on how strict the compiler was asked to be.
+
+ Used in QByteArrayView::lastIndexOf() overload for a single char.
+*/
+const void *qmemrchr(const void *s, int needle, size_t size) noexcept
+{
+#if QT_CONFIG(memrchr)
+ return memrchr(s, needle, size);
+#endif
+ auto b = static_cast<const char *>(s);
+ const char *n = b + size;
+ while (n-- != b) {
+ if (*n == needle)
+ return n;
+ }
+ return nullptr;
+}
+
+
+/*! \relates QByteArray
Returns a duplicate string.
@@ -2680,31 +2700,6 @@ QByteArray QByteArray::repeated(qsizetype times) const
return result;
}
-#define REHASH(a) \
- if (ol_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << ol_minus_1; \
- hashHaystack <<= 1
-
-qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
-{
- const auto ol = needle.size();
- const auto l = haystack.size();
- if (ol == 0) {
- if (from < 0)
- return qMax(from + l, 0);
- else
- return from > l ? -1 : from;
- }
-
- if (ol == 1)
- return findByteArray(haystack, from, needle.front());
-
- if (from > l || ol + from > l)
- return -1;
-
- return qFindByteArray(haystack.data(), haystack.size(), from, needle.data(), ol);
-}
-
/*! \fn qsizetype QByteArray::indexOf(QByteArrayView bv, qsizetype from) const
\since 6.0
@@ -2745,10 +2740,10 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
const char *end = haystack;
haystack += from;
- const auto ol_minus_1 = std::size_t(ol - 1);
+ const qregisteruint ol_minus_1 = ol - 1;
const char *n = needle + ol_minus_1;
const char *h = haystack + ol_minus_1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
for (idx = 0; idx < ol; ++idx) {
hashNeedle = ((hashNeedle<<1) + *(n-idx));
@@ -2760,34 +2755,11 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0)
return haystack - end;
--haystack;
- REHASH(*(haystack + ol));
+ if (ol_minus_1 < sizeof(ol_minus_1) * CHAR_BIT)
+ hashHaystack -= qregisteruint(*(haystack + ol)) << ol_minus_1;
+ hashHaystack <<= 1;
}
return -1;
-
-}
-
-static inline qsizetype lastIndexOfCharHelper(QByteArrayView haystack, qsizetype from, char needle) noexcept
-{
- if (haystack.size() == 0)
- return -1;
- if (from < 0)
- from += haystack.size();
- else if (from > haystack.size())
- from = haystack.size() - 1;
- if (from >= 0) {
- const char *b = haystack.data();
- const char *n = b + from + 1;
- while (n-- != b) {
- if (*n == needle)
- return n - b;
- }
- }
- return -1;
-}
-
-qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept
-{
- return lastIndexOfCharHelper(haystack, from, needle);
}
qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
@@ -2799,7 +2771,7 @@ qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteA
}
const auto ol = needle.size();
if (ol == 1)
- return lastIndexOfCharHelper(haystack, from, needle.front());
+ return QtPrivate::lastIndexOf(haystack, from, needle.front());
return lastIndexOfHelper(haystack.data(), haystack.size(), needle.data(), ol, from);
}
@@ -4218,24 +4190,6 @@ QByteArray QByteArray::toBase64(Base64Options options) const
\sa toUShort()
*/
-static char *qulltoa2(char *p, qulonglong n, int base)
-{
-#if defined(QT_CHECK_RANGE)
- if (base < 2 || base > 36) {
- qWarning("QByteArray::setNum: Invalid base %d", base);
- base = 10;
- }
-#endif
- constexpr char b = 'a' - 10;
- do {
- const int c = n % base;
- n /= base;
- *--p = c + (c < 10 ? '0' : b);
- } while (n);
-
- return p;
-}
-
/*!
\overload
@@ -4255,9 +4209,7 @@ QByteArray &QByteArray::setNum(qlonglong n, int base)
p = qulltoa2(buff + buffsize, qulonglong(n), base);
}
- clear();
- append(p, buffsize - (p - buff));
- return *this;
+ return assign(QByteArrayView{p, buff + buffsize});
}
/*!
@@ -4272,9 +4224,7 @@ QByteArray &QByteArray::setNum(qulonglong n, int base)
char buff[buffsize];
char *p = qulltoa2(buff + buffsize, n, base);
- clear();
- append(p, buffsize - (p - buff));
- return *this;
+ return assign(QByteArrayView{p, buff + buffsize});
}
/*!
@@ -5206,5 +5156,3 @@ size_t qHash(const QByteArray::FromBase64Result &key, size_t seed) noexcept
*/
QT_END_NAMESPACE
-
-#undef REHASH
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 3c8a3bba45..5902b01516 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -136,12 +136,12 @@ public:
[[nodiscard]] char back() const { return at(size() - 1); }
[[nodiscard]] inline char &back();
- QT_CORE_INLINE_SINCE(6, 7)
+ QT_CORE_INLINE_SINCE(6, 8)
qsizetype indexOf(char c, qsizetype from = 0) const;
qsizetype indexOf(QByteArrayView bv, qsizetype from = 0) const
{ return QtPrivate::findByteArray(qToByteArrayViewIgnoringNull(*this), from, bv); }
- QT_CORE_INLINE_SINCE(6, 7)
+ QT_CORE_INLINE_SINCE(6, 8)
qsizetype lastIndexOf(char c, qsizetype from = -1) const;
qsizetype lastIndexOf(QByteArrayView bv) const
{ return lastIndexOf(bv, size()); }
@@ -706,7 +706,7 @@ bool QByteArray::isNull() const noexcept
return d->isNull();
}
#endif
-#if QT_CORE_INLINE_IMPL_SINCE(6, 7)
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
qsizetype QByteArray::indexOf(char ch, qsizetype from) const
{
return qToByteArrayViewIgnoringNull(*this).indexOf(ch, from);
diff --git a/src/corelib/text/qbytearrayalgorithms.h b/src/corelib/text/qbytearrayalgorithms.h
index 7060161bb4..649ec2e39b 100644
--- a/src/corelib/text/qbytearrayalgorithms.h
+++ b/src/corelib/text/qbytearrayalgorithms.h
@@ -31,8 +31,8 @@ qsizetype findByteArray(QByteArrayView haystack, qsizetype from, char needle) no
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
qsizetype findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
-[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
-qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept;
+[[nodiscard]] inline Q_DECL_PURE_FUNCTION
+qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, uchar needle) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
@@ -99,6 +99,8 @@ static inline T toIntegral(ByteArrayView data, bool *ok, int base)
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
+[[nodiscard]] Q_DECL_PURE_FUNCTION Q_CORE_EXPORT
+const void *qmemrchr(const void *s, int needle, size_t n) noexcept;
Q_CORE_EXPORT char *qstrdup(const char *);
inline size_t qstrlen(const char *str)
diff --git a/src/corelib/text/qbytearraymatcher.cpp b/src/corelib/text/qbytearraymatcher.cpp
index ae38fb584b..9f27e10f3d 100644
--- a/src/corelib/text/qbytearraymatcher.cpp
+++ b/src/corelib/text/qbytearraymatcher.cpp
@@ -3,6 +3,11 @@
#include "qbytearraymatcher.h"
+#include <qtconfiginclude.h>
+#ifndef QT_BOOTSTRAPPED
+# include <private/qtcore-config_p.h>
+#endif
+
#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -212,26 +217,10 @@ qsizetype QByteArrayMatcher::indexIn(QByteArrayView data, qsizetype from) const
\sa setPattern()
*/
-
-static qsizetype findChar(const char *str, qsizetype len, char ch, qsizetype from)
-{
- const uchar *s = (const uchar *)str;
- uchar c = (uchar)ch;
- if (from < 0)
- from = qMax(from + len, qsizetype(0));
- if (from < len) {
- const uchar *n = s + from - 1;
- const uchar *e = s + len;
- while (++n != e)
- if (*n == c)
- return n - s;
- }
- return -1;
-}
-
/*!
\internal
*/
+Q_NEVER_INLINE
static qsizetype qFindByteArrayBoyerMoore(
const char *haystack, qsizetype haystackLen, qsizetype haystackOffset,
const char *needle, qsizetype needleLen)
@@ -244,20 +233,21 @@ static qsizetype qFindByteArrayBoyerMoore(
(const uchar *)needle, needleLen, skiptable);
}
-#define REHASH(a) \
- if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << sl_minus_1; \
- hashHaystack <<= 1
-
/*!
\internal
*/
-qsizetype qFindByteArray(
- const char *haystack0, qsizetype haystackLen, qsizetype from,
- const char *needle, qsizetype needleLen)
+static qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
+ const char *needle, qsizetype sl);
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
- const auto l = haystackLen;
- const auto sl = needleLen;
+ const auto haystack0 = haystack.data();
+ const auto l = haystack.size();
+ const auto sl = needle.size();
+#if !QT_CONFIG(memmem)
+ if (sl == 1)
+ return findByteArray(haystack, from, needle.front());
+#endif
+
if (from < 0)
from += l;
if (std::size_t(sl + from) > std::size_t(l))
@@ -267,8 +257,10 @@ qsizetype qFindByteArray(
if (!l)
return -1;
- if (sl == 1)
- return findChar(haystack0, haystackLen, needle[0], from);
+#if QT_CONFIG(memmem)
+ auto where = memmem(haystack0 + from, l - from, needle.data(), sl);
+ return where ? static_cast<const char *>(where) - haystack0 : -1;
+#endif
/*
We use the Boyer-Moore algorithm in cases where the overhead
@@ -276,18 +268,22 @@ qsizetype qFindByteArray(
hash function.
*/
if (l > 500 && sl > 5)
- return qFindByteArrayBoyerMoore(haystack0, haystackLen, from,
- needle, needleLen);
+ return qFindByteArrayBoyerMoore(haystack0, l, from, needle.data(), sl);
+ return qFindByteArray(haystack0, l, from, needle.data(), sl);
+}
+qsizetype qFindByteArray(const char *haystack0, qsizetype l, qsizetype from,
+ const char *needle, qsizetype sl)
+{
/*
We use some hashing for efficiency's sake. Instead of
comparing strings, we compare the hash value of str with that
- of a part of this QString. Only if that matches, we call memcmp().
+ of a part of this QByteArray. Only if that matches, we call memcmp().
*/
const char *haystack = haystack0 + from;
const char *end = haystack0 + (l - sl);
- const auto sl_minus_1 = std::size_t(sl - 1);
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ const qregisteruint sl_minus_1 = sl - 1;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
for (idx = 0; idx < sl; ++idx) {
hashNeedle = ((hashNeedle<<1) + needle[idx]);
@@ -301,7 +297,9 @@ qsizetype qFindByteArray(
&& memcmp(needle, haystack, sl) == 0)
return haystack - haystack0;
- REHASH(*haystack);
+ if (sl_minus_1 < sizeof(sl_minus_1) * CHAR_BIT)
+ hashHaystack -= qregisteruint(*haystack) << sl_minus_1;
+ hashHaystack <<= 1;
++haystack;
}
return -1;
@@ -409,7 +407,4 @@ qsizetype QStaticByteArrayMatcherBase::indexOfIn(const char *needle, size_t nlen
\snippet code/src_corelib_text_qbytearraymatcher.cpp 1
*/
-
QT_END_NAMESPACE
-
-#undef REHASH
diff --git a/src/corelib/text/qbytearrayview.h b/src/corelib/text/qbytearrayview.h
index 45ebc812cd..358c9e62ef 100644
--- a/src/corelib/text/qbytearrayview.h
+++ b/src/corelib/text/qbytearrayview.h
@@ -169,7 +169,8 @@ public:
: QByteArrayView(data, lengthHelperCharArray(data, Size)) {}
constexpr QByteArrayView(QLatin1StringView v) noexcept; // defined in qlatin1stringview.h
- constexpr QByteArrayView(QUtf8StringView v) noexcept; // defined in qutf8stringview.h
+ template <bool UseChar8T>
+ constexpr QByteArrayView(QBasicUtf8StringView<UseChar8T> v) noexcept; // defined in qutf8stringview.h
#ifdef Q_QDOC
template <typename Byte, size_t Size>
@@ -401,6 +402,18 @@ qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, char
return -1;
}
+qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, uchar needle) noexcept
+{
+ if (from < 0)
+ from = qMax(from + haystack.size(), qsizetype(0));
+ else
+ from = qMin(from, haystack.size() - 1);
+
+ const char *const b = haystack.data();
+ const void *n = b ? qmemrchr(b, needle, from + 1) : nullptr;
+ return n ? static_cast<const char *>(n) - b : -1;
+}
+
QT_END_NAMESPACE
#endif // QBYTEARRAYVIEW_H
diff --git a/src/corelib/text/qchar.cpp b/src/corelib/text/qchar.cpp
index 63296a92de..7b114e9723 100644
--- a/src/corelib/text/qchar.cpp
+++ b/src/corelib/text/qchar.cpp
@@ -123,9 +123,7 @@ QT_BEGIN_NAMESPACE
Starting with Qt 6.0, most QChar constructors are \c explicit. This
is done to avoid dangerous mistakes when accidentally mixing
- integral types and strings. You can opt-out (and make these
- constructors implicit) by defining the macro \c
- QT_IMPLICIT_QCHAR_CONSTRUCTION.
+ integral types and strings.
For more information see
\l{https://www.unicode.org/ucd/}{"About the Unicode Character Database"}.
@@ -2110,51 +2108,4 @@ static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationFo
return true;
}
-/*!
- \macro QT_IMPLICIT_QCHAR_CONSTRUCTION
- \since 6.0
- \relates QChar
-
- Defining this macro makes certain QChar constructors implicit
- rather than explicit. This is done to enforce safe conversions:
-
- \badcode
-
- QString str = getString();
- if (str == 123) {
- // Oops, meant str == "123". By default does not compile,
- // *unless* this macro is defined, in which case, it's interpreted
- // as `if (str == QChar(123))`, that is, `if (str == '{')`.
- // Likely, not what we meant.
- }
-
- \endcode
-
- This macro is provided to keep existing code working; it is
- recommended to instead use explicit conversions and/or QLatin1Char.
- For instance:
-
- \code
-
- QChar c1 = 'x'; // OK, unless QT_NO_CAST_FROM_ASCII is defined
- QChar c2 = u'x'; // always OK, recommended
- QChar c3 = QLatin1Char('x'); // always OK, recommended
-
- // from int to 1 UTF-16 code unit: must guarantee that the input is <= 0xFFFF
- QChar c4 = 120; // compile error, unless QT_IMPLICIT_QCHAR_CONSTRUCTION is defined
- QChar c5(120); // OK (direct initialization)
- auto c6 = QChar(120); // ditto
-
- // from int/char32_t to 1/2 UTF-16 code units:
- // 𝄞 'MUSICAL SYMBOL G CLEF' (U+1D11E)
- auto c7 = QChar(0x1D11E); // compiles, but undefined behavior at runtime
- auto c8 = QChar::fromUcs4(0x1D11E); // always OK
- auto c9 = QChar::fromUcs4(U'\U0001D11E'); // always OK
- // => use c8/c9 as QStringView objects
-
- \endcode
-
- \sa QLatin1Char, QChar::fromUcs4, QT_NO_CAST_FROM_ASCII
-*/
-
QT_END_NAMESPACE
diff --git a/src/corelib/text/qchar.h b/src/corelib/text/qchar.h
index c0c53664c2..b3fd794726 100644
--- a/src/corelib/text/qchar.h
+++ b/src/corelib/text/qchar.h
@@ -63,17 +63,15 @@ public:
};
#ifdef QT_IMPLICIT_QCHAR_CONSTRUCTION
-#define QCHAR_MAYBE_IMPLICIT Q_IMPLICIT
-#else
-#define QCHAR_MAYBE_IMPLICIT explicit
+#error This macro has been removed in Qt 6.8.
#endif
constexpr Q_IMPLICIT QChar() noexcept : ucs(0) {}
constexpr Q_IMPLICIT QChar(ushort rc) noexcept : ucs(rc) {}
- constexpr QCHAR_MAYBE_IMPLICIT QChar(uchar c, uchar r) noexcept : ucs(char16_t((r << 8) | c)) {}
+ constexpr explicit QChar(uchar c, uchar r) noexcept : ucs(char16_t((r << 8) | c)) {}
constexpr Q_IMPLICIT QChar(short rc) noexcept : ucs(char16_t(rc)) {}
- constexpr QCHAR_MAYBE_IMPLICIT QChar(uint rc) noexcept : ucs((Q_ASSERT(rc <= 0xffff), char16_t(rc))) {}
- constexpr QCHAR_MAYBE_IMPLICIT QChar(int rc) noexcept : QChar(uint(rc)) {}
+ constexpr explicit QChar(uint rc) noexcept : ucs((Q_ASSERT(rc <= 0xffff), char16_t(rc))) {}
+ constexpr explicit QChar(int rc) noexcept : QChar(uint(rc)) {}
constexpr Q_IMPLICIT QChar(SpecialCharacter s) noexcept : ucs(char16_t(s)) {}
constexpr Q_IMPLICIT QChar(QLatin1Char ch) noexcept : ucs(ch.unicode()) {}
constexpr Q_IMPLICIT QChar(char16_t ch) noexcept : ucs(ch) {}
@@ -85,12 +83,10 @@ public:
// Always implicit -- allow for 'x' => QChar conversions
QT_ASCII_CAST_WARN constexpr Q_IMPLICIT QChar(char c) noexcept : ucs(uchar(c)) { }
#ifndef QT_RESTRICTED_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN constexpr QCHAR_MAYBE_IMPLICIT QChar(uchar c) noexcept : ucs(c) { }
+ QT_ASCII_CAST_WARN constexpr explicit QChar(uchar c) noexcept : ucs(c) { }
#endif
#endif
-#undef QCHAR_MAYBE_IMPLICIT
-
static constexpr QChar fromUcs2(char16_t c) noexcept { return QChar{c}; }
static constexpr inline auto fromUcs4(char32_t c) noexcept;
diff --git a/src/corelib/text/qlatin1stringmatcher.cpp b/src/corelib/text/qlatin1stringmatcher.cpp
index 68bf97db5c..9036048fff 100644
--- a/src/corelib/text/qlatin1stringmatcher.cpp
+++ b/src/corelib/text/qlatin1stringmatcher.cpp
@@ -160,6 +160,31 @@ Qt::CaseSensitivity QLatin1StringMatcher::caseSensitivity() const noexcept
*/
qsizetype QLatin1StringMatcher::indexIn(QLatin1StringView haystack, qsizetype from) const noexcept
{
+ return indexIn_helper(haystack, from);
+}
+
+/*!
+ \since 6.8
+ \overload
+
+ Searches for the pattern in the given \a haystack starting from index
+ position \a from.
+
+ \sa caseSensitivity(), pattern()
+*/
+qsizetype QLatin1StringMatcher::indexIn(QStringView haystack, qsizetype from) const noexcept
+{
+ return indexIn_helper(haystack, from);
+}
+
+/*!
+ \internal
+*/
+template <typename String>
+qsizetype QLatin1StringMatcher::indexIn_helper(String haystack, qsizetype from) const noexcept
+{
+ static_assert(QtPrivate::isLatin1OrUtf16View<String>);
+
if (m_pattern.isEmpty() && from == haystack.size())
return from;
if (from < 0) // Historical behavior (see QString::indexOf and co.)
@@ -167,8 +192,15 @@ qsizetype QLatin1StringMatcher::indexIn(QLatin1StringView haystack, qsizetype fr
if (from >= haystack.size())
return -1;
- auto begin = haystack.begin() + from;
- auto end = haystack.end();
+ const auto start = [haystack] {
+ if constexpr (std::is_same_v<String, QStringView>)
+ return haystack.utf16();
+ else
+ return haystack.begin();
+ }();
+
+ auto begin = start + from;
+ auto end = start + haystack.size();
auto found = begin;
if (m_cs == Qt::CaseSensitive) {
found = m_caseSensitiveSearcher(begin, end, m_pattern.begin(), m_pattern.end()).begin;
@@ -178,7 +210,7 @@ qsizetype QLatin1StringMatcher::indexIn(QLatin1StringView haystack, qsizetype fr
const qsizetype bufferSize = std::min(m_pattern.size(), qsizetype(sizeof m_foldBuffer));
const QLatin1StringView restNeedle = m_pattern.sliced(bufferSize);
const bool needleLongerThanBuffer = restNeedle.size() > 0;
- QLatin1StringView restHaystack = haystack;
+ String restHaystack = haystack;
do {
found = m_caseInsensitiveSearcher(found, end, m_foldBuffer, &m_foldBuffer[bufferSize])
.begin;
@@ -189,13 +221,13 @@ qsizetype QLatin1StringMatcher::indexIn(QLatin1StringView haystack, qsizetype fr
}
restHaystack = haystack.sliced(
qMin(haystack.size(),
- bufferSize + qsizetype(std::distance(haystack.begin(), found))));
+ bufferSize + qsizetype(std::distance(start, found))));
if (restHaystack.startsWith(restNeedle, Qt::CaseInsensitive))
break;
++found;
} while (true);
}
- return std::distance(haystack.begin(), found);
+ return std::distance(start, found);
}
QT_END_NAMESPACE
diff --git a/src/corelib/text/qlatin1stringmatcher.h b/src/corelib/text/qlatin1stringmatcher.h
index 3b8c24fc92..dd3414fc6d 100644
--- a/src/corelib/text/qlatin1stringmatcher.h
+++ b/src/corelib/text/qlatin1stringmatcher.h
@@ -14,6 +14,10 @@
QT_BEGIN_NAMESPACE
namespace QtPrivate {
+template <typename T>
+constexpr inline bool isLatin1OrUtf16View =
+ std::disjunction_v<std::is_same<T, QLatin1StringView>, std::is_same<T, QStringView>>;
+
template<class RandomIt1,
class Hash = std::hash<typename std::iterator_traits<RandomIt1>::value_type>,
class BinaryPredicate = std::equal_to<>>
@@ -147,6 +151,7 @@ public:
Q_CORE_EXPORT Qt::CaseSensitivity caseSensitivity() const noexcept;
Q_CORE_EXPORT qsizetype indexIn(QLatin1StringView haystack, qsizetype from = 0) const noexcept;
+ Q_CORE_EXPORT qsizetype indexIn(QStringView haystack, qsizetype from = 0) const noexcept;
private:
void setSearcher() noexcept;
@@ -164,6 +169,10 @@ private:
CaseSensitiveSearcher m_caseSensitiveSearcher;
CaseInsensitiveSearcher m_caseInsensitiveSearcher;
};
+
+ template <typename String>
+ qsizetype indexIn_helper(String haystack, qsizetype from) const noexcept;
+
char m_foldBuffer[256];
};
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index ab95b300eb..86ab072b73 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -4760,6 +4760,11 @@ QStringList QLocale::uiLanguages(TagSeparator separator) const
const bool isSystem = d->m_data == &systemLocaleData;
if (isSystem) {
uiLanguages = systemLocale()->query(QSystemLocale::UILanguages).toStringList();
+ if (separator != TagSeparator::Dash) {
+ // Map from default separator, Dash, used by backends:
+ const QChar join = QLatin1Char(sep);
+ uiLanguages = uiLanguages.replaceInStrings(u"-", QStringView(&join, 1));
+ }
// ... but we need to include likely-adjusted forms of each of those, too.
// For now, collect up locale Ids representing the entries, for later processing:
for (const auto &entry : std::as_const(uiLanguages))
diff --git a/src/corelib/text/qlocale.h b/src/corelib/text/qlocale.h
index cb3eb64193..abef24ea0e 100644
--- a/src/corelib/text/qlocale.h
+++ b/src/corelib/text/qlocale.h
@@ -1173,8 +1173,11 @@ private:
friend class QRomanCalendar;
friend Q_CORE_EXPORT size_t qHash(const QLocale &key, size_t seed) noexcept;
- friend bool operator==(const QLocale &lhs, const QLocale &rhs) { return lhs.equals(rhs); }
- friend bool operator!=(const QLocale &lhs, const QLocale &rhs) { return !lhs.equals(rhs); }
+ friend bool comparesEqual(const QLocale &lhs, const QLocale &rhs) noexcept
+ {
+ return lhs.equals(rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QLocale)
QSharedDataPointer<QLocalePrivate> d;
};
diff --git a/src/corelib/text/qlocale.qdoc b/src/corelib/text/qlocale.qdoc
index f3f0a5cc2d..0cdacfd8e5 100644
--- a/src/corelib/text/qlocale.qdoc
+++ b/src/corelib/text/qlocale.qdoc
@@ -7,6 +7,7 @@
\brief The QLocale class converts between numbers and their
string representations in various languages.
+ \compares equality
\reentrant
\ingroup i18n
\ingroup string-processing
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp
index b6639bcb71..6b04bc92cd 100644
--- a/src/corelib/text/qlocale_tools.cpp
+++ b/src/corelib/text/qlocale_tools.cpp
@@ -552,6 +552,18 @@ QString qulltoa(qulonglong number, int base, const QStringView zero)
return QString(reinterpret_cast<QChar *>(p), end - p);
}
+char *qulltoa2(char *p, qulonglong n, int base)
+{
+#if defined(QT_CHECK_RANGE)
+ if (base < 2 || base > 36) {
+ qWarning("QByteArray::setNum: Invalid base %d", base);
+ base = 10;
+ }
+#endif
+ qulltoString_helper(n, base, p);
+ return p;
+}
+
/*!
\internal
@@ -795,4 +807,79 @@ QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, int precision, bool
return dtoString<QByteArray>(d, form, precision, uppercase);
}
+#if defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128)
+static inline quint64 toUInt64(qinternaluint128 v)
+{
+#if defined(QT_USE_MSVC_INT128)
+ return quint64(v._Word[0]);
+#else
+ return quint64(v);
+#endif
+}
+
+QString quint128toBasicLatin(qinternaluint128 number, int base)
+{
+ // We divide our 128-bit number into parts that we can do text
+ // concatenation with. This list is the maximum power of the
+ // base that is less than 2^64.
+ static constexpr auto dividers = []() constexpr {
+ std::array<quint64, 35> bases {};
+ for (int base = 2; base <= 36; ++base) {
+ quint64 v = base;
+ while (v * base > v)
+ v *= base;
+ bases[base - 2] = v;
+ }
+ return bases;
+ }();
+ static constexpr auto digitCounts = []() constexpr {
+ std::array<quint8, 35> digits{};
+ for (int base = 2; base <= 36; ++base) {
+ quint64 v = base;
+ int i = 0;
+ for (i = 0; v * base > v; ++i)
+ v *= base;
+ digits[base - 2] = i;
+ }
+ return digits;
+ }();
+
+ QString result;
+
+ constexpr unsigned flags = QLocaleData::NoFlags;
+ const QLocaleData *dd = QLocaleData::c();
+
+ // special base cases:
+ constexpr int Width = -1;
+ if (base == 2 || base == 4 || base == 16) {
+ // 2^64 is a power of 2, 4 and 16
+ result = dd->unsLongLongToString(quint64(number), 64, base, Width, flags);
+ result.prepend(dd->unsLongLongToString(quint64(number >> 64), -1, base, Width, flags));
+ } else {
+ int digitCount = digitCounts[base - 2];
+ quint64 divider = dividers[base - 2];
+ quint64 lower = toUInt64(number % divider);
+ number /= divider;
+ while (number) {
+ result.prepend(dd->unsLongLongToString(lower, digitCount, base, Width, flags));
+ lower = toUInt64(number % divider);
+ number /= divider;
+ }
+ result.prepend(dd->unsLongLongToString(lower, -1, base, Width, flags));
+ }
+ return result;
+}
+
+QString qint128toBasicLatin(qinternalint128 number, int base)
+{
+ const bool negative = number < 0;
+ if (negative)
+ number *= -1;
+ QString result = quint128toBasicLatin(qinternaluint128(number), base);
+ if (negative)
+ result.prepend(u'-');
+ return result;
+}
+#endif // defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128)
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qlocale_tools_p.h b/src/corelib/text/qlocale_tools_p.h
index 9b02403ea4..2cfe25d299 100644
--- a/src/corelib/text/qlocale_tools_p.h
+++ b/src/corelib/text/qlocale_tools_p.h
@@ -18,8 +18,21 @@
#include "qlocale_p.h"
#include "qstring.h"
+#if !defined(QT_SUPPORTS_INT128) && (defined(Q_CC_MSVC) && (_MSC_VER >= 1930) && __has_include(<__msvc_int128.hpp>))
+#include <__msvc_int128.hpp>
+#define QT_USE_MSVC_INT128
+#endif
+
QT_BEGIN_NAMESPACE
+#if defined(QT_SUPPORTS_INT128)
+using qinternalint128 = qint128;
+using qinternaluint128 = quint128;
+#elif defined(QT_USE_MSVC_INT128)
+using qinternalint128 = std::_Signed128;
+using qinternaluint128 = std::_Unsigned128;
+#endif
+
enum StrayCharacterMode {
TrailingJunkProhibited,
TrailingJunkAllowed,
@@ -36,12 +49,20 @@ void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision,
[[nodiscard]] QString qulltoBasicLatin(qulonglong l, int base, bool negative);
[[nodiscard]] QString qulltoa(qulonglong l, int base, const QStringView zero);
+[[nodiscard]] char *qulltoa2(char *p, qulonglong n, int base);
[[nodiscard]] Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign);
[[nodiscard]] QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form,
int precision, bool uppercase);
[[nodiscard]] QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form,
int precision, bool uppercase);
+#if defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128)
+[[nodiscard]] Q_CORE_EXPORT QString quint128toBasicLatin(qinternaluint128 number,
+ int base = 10);
+[[nodiscard]] Q_CORE_EXPORT QString qint128toBasicLatin(qinternalint128 number,
+ int base = 10);
+#endif
+
[[nodiscard]] constexpr inline bool isZero(double d)
{
return d == 0; // Amusingly, compilers do not grumble.
diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp
index 67c422568b..78261e14cb 100644
--- a/src/corelib/text/qregularexpression.cpp
+++ b/src/corelib/text/qregularexpression.cpp
@@ -42,6 +42,7 @@ using namespace Qt::StringLiterals;
\keyword regular expression
+ \compares equality
Regular expressions, or \e{regexps}, are a very powerful tool to handle
strings and texts. This is useful in many contexts, e.g.,
@@ -1734,18 +1735,20 @@ void QRegularExpression::optimize() const
}
/*!
- Returns \c true if the regular expression is equal to \a re, or false
+ \fn bool QRegularExpression::operator==(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
+
+ Returns \c true if the \a lhs regular expression is equal to the \a rhs, or false
otherwise. Two QRegularExpression objects are equal if they have
the same pattern string and the same pattern options.
\sa operator!=()
*/
-bool QRegularExpression::operator==(const QRegularExpression &re) const
+bool comparesEqual(const QRegularExpression &lhs,
+ const QRegularExpression &rhs) noexcept
{
- return (d == re.d) ||
- (d->pattern == re.d->pattern && d->patternOptions == re.d->patternOptions);
+ return (lhs.d == rhs.d) ||
+ (lhs.d->pattern == rhs.d->pattern && lhs.d->patternOptions == rhs.d->patternOptions);
}
-
/*!
\fn QRegularExpression & QRegularExpression::operator=(QRegularExpression && re)
@@ -1758,9 +1761,9 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const
*/
/*!
- \fn bool QRegularExpression::operator!=(const QRegularExpression &re) const
+ \fn bool QRegularExpression::operator!=(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
- Returns \c true if the regular expression is different from \a re, or
+ Returns \c true if the \a lhs regular expression is different from the \a rhs, or
false otherwise.
\sa operator==()
diff --git a/src/corelib/text/qregularexpression.h b/src/corelib/text/qregularexpression.h
index 2b51b94b15..ab147b87d4 100644
--- a/src/corelib/text/qregularexpression.h
+++ b/src/corelib/text/qregularexpression.h
@@ -157,11 +157,15 @@ public:
static QRegularExpression fromWildcard(QStringView pattern, Qt::CaseSensitivity cs = Qt::CaseInsensitive,
WildcardConversionOptions options = DefaultWildcardConversion);
-
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QRegularExpression &re) const;
inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); }
-
+#endif
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QRegularExpression &lhs,
+ const QRegularExpression &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpression)
+
friend struct QRegularExpressionPrivate;
friend class QRegularExpressionMatch;
friend struct QRegularExpressionMatchPrivate;
@@ -365,30 +369,24 @@ private:
// [input.iterators] imposes operator== on us. Unfortunately, it's not
// trivial to implement, so just do the bare minimum to satifisfy
// Cpp17EqualityComparable.
- friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
- const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
+ friend bool comparesEqual(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
+ const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs)
+ noexcept
{
return (&lhs == &rhs);
}
-
- friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
- const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
- {
- return !(lhs == rhs);
- }
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpressionMatchIteratorRangeBasedForIterator)
// This is what we really use in a range-based for.
- friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
- QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
+ friend bool comparesEqual(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
+ const QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel &rhs)
+ noexcept
{
+ Q_UNUSED(rhs);
return lhs.m_atEnd;
}
-
- friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
- QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
- {
- return !lhs.m_atEnd;
- }
+ Q_DECLARE_EQUALITY_COMPARABLE(QRegularExpressionMatchIteratorRangeBasedForIterator,
+ QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel)
QRegularExpressionMatchIterator m_matchIterator;
QRegularExpressionMatch m_currentMatch;
diff --git a/src/corelib/text/qstaticlatin1stringmatcher.h b/src/corelib/text/qstaticlatin1stringmatcher.h
index d80ebd8547..bd6d9db08b 100644
--- a/src/corelib/text/qstaticlatin1stringmatcher.h
+++ b/src/corelib/text/qstaticlatin1stringmatcher.h
@@ -109,13 +109,30 @@ public:
}
constexpr qsizetype indexIn(QLatin1StringView haystack, qsizetype from = 0) const noexcept
+ { return indexIn_helper(haystack, from); }
+
+ constexpr qsizetype indexIn(QStringView haystack, qsizetype from = 0) const noexcept
+ { return indexIn_helper(haystack, from); }
+
+private:
+ template <typename String>
+ constexpr qsizetype indexIn_helper(String haystack, qsizetype from = 0) const noexcept
{
+ static_assert(QtPrivate::isLatin1OrUtf16View<String>);
+
if (from >= haystack.size())
return -1;
- const char *begin = haystack.begin() + from;
- const char *end = haystack.end();
+
+ const auto start = [haystack]() constexpr {
+ if constexpr (std::is_same_v<String, QStringView>)
+ return haystack.utf16();
+ else
+ return haystack.begin();
+ }();
+ const auto begin = start + from;
+ const auto end = start + haystack.size();
const auto r = m_searcher(begin, end, m_pattern.begin(), m_pattern.end());
- return r.begin == end ? -1 : std::distance(haystack.begin(), r.begin);
+ return r.begin == end ? -1 : std::distance(start, r.begin);
}
};
diff --git a/src/corelib/text/qstaticlatin1stringmatcher.qdoc b/src/corelib/text/qstaticlatin1stringmatcher.qdoc
index 6577f985b2..86edf69bc2 100644
--- a/src/corelib/text/qstaticlatin1stringmatcher.qdoc
+++ b/src/corelib/text/qstaticlatin1stringmatcher.qdoc
@@ -44,6 +44,7 @@
/*!
\fn template<Qt::CaseSensitivity CS, size_t N> constexpr qsizetype QStaticLatin1StringMatcher<CS, N>::indexIn(QLatin1StringView haystack, qsizetype from) const
+ \fn template<Qt::CaseSensitivity CS, size_t N> constexpr qsizetype QStaticLatin1StringMatcher<CS, N>::indexIn(QStringView haystack, qsizetype from) const
Searches the QLatin1StringView \a haystack, from byte position \a from
(default 0, i.e. from the first byte), for QLatin1StringView pattern()
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index f0bf0c50a3..2d0e4531d1 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -63,8 +63,8 @@
#endif
#define REHASH(a) \
- if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
- hashHaystack -= std::size_t(a) << sl_minus_1; \
+ if (sl_minus_1 < sizeof(sl_minus_1) * CHAR_BIT) \
+ hashHaystack -= decltype(hashHaystack)(a) << sl_minus_1; \
hashHaystack <<= 1
QT_BEGIN_NAMESPACE
@@ -183,10 +183,10 @@ static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
const auto needle = needle0.data();
const auto *end = haystack;
haystack += from;
- const std::size_t sl_minus_1 = sl ? sl - 1 : 0;
+ const qregisteruint sl_minus_1 = sl ? sl - 1 : 0;
const auto *n = needle + sl_minus_1;
const auto *h = haystack + sl_minus_1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
if (cs == Qt::CaseSensitive) {
for (qsizetype idx = 0; idx < sl; ++idx) {
@@ -361,7 +361,7 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const char16_t *src, int le
#if defined(__SSE2__) && defined(Q_CC_GNU)
// We may overrun the buffer, but that's a false positive:
// this won't crash nor produce incorrect results
-# define ATTRIBUTE_NO_SANITIZE __attribute__((__no_sanitize_address__))
+# define ATTRIBUTE_NO_SANITIZE __attribute__((__no_sanitize_address__, __no_sanitize_thread__))
#else
# define ATTRIBUTE_NO_SANITIZE
#endif
@@ -657,7 +657,7 @@ static int ucstrncmp_sse2(const char16_t *a, const Char *b, size_t l)
Q_NEVER_INLINE
qsizetype QtPrivate::qustrlen(const char16_t *str) noexcept
{
-#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
+#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && !(defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer))
return qustrlen_sse2(str);
#endif
@@ -1543,6 +1543,8 @@ int QtPrivate::compareStrings(QLatin1StringView lhs, QLatin1StringView rhs, Qt::
{
if (lhs.isEmpty())
return qt_lencmp(qsizetype(0), rhs.size());
+ if (rhs.isEmpty())
+ return qt_lencmp(lhs.size(), qsizetype(0));
if (cs == Qt::CaseInsensitive)
return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
const auto l = std::min(lhs.size(), rhs.size());
@@ -5251,8 +5253,9 @@ QString QString::section(const QRegularExpression &re, qsizetype start, qsizetyp
\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.
+ Returns a substring that contains the \a n leftmost characters of
+ this string (that is, from the beginning of this string up to, but not
+ including, the element at index position \a n).
If you know that \a n cannot be out of bounds, use first() instead in new
code, because it is faster.
@@ -5283,8 +5286,9 @@ QString QString::section(const QRegularExpression &re, qsizetype start, qsizetyp
\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.
+ Returns a string that contains \a n characters of this string, starting
+ at the specified \a position index up to, but not including, the element
+ at index position \c {\a position + n}.
If you know that \a position and \a n cannot be out of bounds, use sliced()
instead in new code, because it is faster.
@@ -5339,8 +5343,9 @@ QString QString::mid(qsizetype position, qsizetype n) &&
\fn QString QString::first(qsizetype n) &&
\since 6.0
- Returns a string that contains the first \a n characters
- of this string.
+ Returns a string that contains the first \a n characters of this string,
+ (that is, from the beginning of this string up to, but not including,
+ the element at index position \a n).
\note The behavior is undefined when \a n < 0 or \a n > size().
@@ -5368,8 +5373,9 @@ QString QString::mid(qsizetype position, qsizetype n) &&
\fn QString QString::sliced(qsizetype pos, qsizetype n) &&
\since 6.0
- Returns a string that contains \a n characters of this string,
- starting at position \a pos.
+ Returns a string that contains \a n characters of this string, starting
+ at position \a pos up to, but not including, the element at index position
+ \c {\a pos + n}.
\note The behavior is undefined when \a pos < 0, \a n < 0,
or \a pos + \a n > size().
@@ -5405,8 +5411,9 @@ QString QString::sliced_helper(QString &str, qsizetype pos, qsizetype n)
\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.
+ Modifies this string to start at position \a pos, up to, but not including,
+ the character (code point) at index position \c {\a pos + n}; 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().
@@ -6302,7 +6309,8 @@ QString QString::trimmed_helper(QString &str)
/*!
\fn void QString::truncate(qsizetype position)
- Truncates the string at the given \a position index.
+ Truncates the string starting from, and including, the element at index
+ \a position.
If the specified \a position index is beyond the end of the
string, nothing happens.
@@ -9140,18 +9148,13 @@ namespace {
struct Part
{
Part() = default; // for QVarLengthArray; do not use
- constexpr Part(QStringView s, int num = -1)
- : tag{QtPrivate::ArgBase::U16}, number{num}, data{s.utf16()}, size{s.size()} {}
- constexpr Part(QLatin1StringView s, int num = -1)
- : tag{QtPrivate::ArgBase::L1}, number{num}, data{s.data()}, size{s.size()} {}
+ constexpr Part(QAnyStringView s, int num = -1)
+ : string{s}, number{num} {}
- void reset(QStringView s) noexcept { *this = {s, number}; }
- void reset(QLatin1StringView s) noexcept { *this = {s, number}; }
+ void reset(QAnyStringView s) noexcept { *this = {s, number}; }
- QtPrivate::ArgBase::Tag tag;
+ QAnyStringView string;
int number;
- const void *data;
- qsizetype size;
};
} // unnamed namespace
@@ -9234,16 +9237,13 @@ static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const A
}
}
}
- totalSize += part.size;
+ totalSize += part.string.size();
}
return totalSize;
}
} // unnamed namespace
-Q_ALWAYS_INLINE QString to_string(QLatin1StringView s) noexcept { return s; }
-Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); }
-
template <typename StringView>
static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPrivate::ArgBase **args)
{
@@ -9257,7 +9257,7 @@ static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPriv
argIndexToPlaceholderMap.resize(qsizetype(numArgs));
else if (Q_UNLIKELY(static_cast<size_t>(argIndexToPlaceholderMap.size()) < numArgs)) // 3b
qWarning("QString::arg: %d argument(s) missing in %ls",
- int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(to_string(pattern)));
+ int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(pattern.toString()));
// 5
const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args);
@@ -9266,24 +9266,33 @@ static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPriv
QString result(totalSize, Qt::Uninitialized);
auto out = const_cast<QChar*>(result.constData());
- for (const Part &part : parts) {
- switch (part.tag) {
- case QtPrivate::ArgBase::L1:
- if (part.size) {
+ struct Concatenate {
+ QChar *out;
+ QChar *operator()(QLatin1String part) noexcept
+ {
+ if (part.size()) {
qt_from_latin1(reinterpret_cast<char16_t*>(out),
- reinterpret_cast<const char*>(part.data), part.size);
+ part.data(), part.size());
}
- break;
- case QtPrivate::ArgBase::U8:
- Q_UNREACHABLE(); // waiting for QUtf8String
- break;
- case QtPrivate::ArgBase::U16:
- if (part.size)
- memcpy(out, part.data, part.size * sizeof(QChar));
- break;
+ return out + part.size();
}
- out += part.size;
- }
+ QChar *operator()(QUtf8StringView part) noexcept
+ {
+ return QUtf8::convertToUnicode(out, part);
+ }
+ QChar *operator()(QStringView part) noexcept
+ {
+ if (part.size())
+ memcpy(out, part.data(), part.size() * sizeof(QChar));
+ return out + part.size();
+ }
+ };
+
+ for (const Part &part : parts)
+ out = part.string.visit(Concatenate{out});
+
+ // UTF-8 decoding may have caused an overestimate of totalSize - correct it:
+ result.truncate(out - result.cbegin());
return result;
}
@@ -9905,8 +9914,8 @@ qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringVi
const char16_t *needle = needle0.utf16();
const char16_t *haystack = haystack0.utf16() + from;
const char16_t *end = haystack0.utf16() + (l - sl);
- const std::size_t sl_minus_1 = sl - 1;
- std::size_t hashNeedle = 0, hashHaystack = 0;
+ const qregisteruint sl_minus_1 = sl - 1;
+ qregisteruint hashNeedle = 0, hashHaystack = 0;
qsizetype idx;
if (cs == Qt::CaseSensitive) {
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 895ec4b5c0..98c2f3cdb0 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -287,7 +287,7 @@ public:
static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0);
static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
- [[nodiscard]] QT_CORE_INLINE_SINCE(6, 7)
+ [[nodiscard]] QT_CORE_INLINE_SINCE(6, 8)
qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
[[nodiscard]] qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
[[nodiscard]] qsizetype indexOf(const QString &s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -295,7 +295,7 @@ public:
{ return QtPrivate::findString(*this, from, s, cs); }
[[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return lastIndexOf(c, -1, cs); }
- [[nodiscard]] QT_CORE_INLINE_SINCE(6, 7)
+ [[nodiscard]] QT_CORE_INLINE_SINCE(6, 8)
qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
[[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
{ return lastIndexOf(s, size(), cs); }
@@ -1510,7 +1510,7 @@ quint64 QString::toULongLong(bool *ok, int base) const
return toIntegral_helper<qulonglong>(*this, ok, base);
}
#endif
-#if QT_CORE_INLINE_IMPL_SINCE(6, 7)
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
qsizetype QString::indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const
{
return qToStringViewIgnoringNull(*this).indexOf(ch, from, cs);
diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h
index 71a1dbd526..755e3f82bd 100644
--- a/src/corelib/text/qstringalgorithms.h
+++ b/src/corelib/text/qstringalgorithms.h
@@ -56,7 +56,6 @@ namespace QtPrivate {
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1StringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1StringView haystack, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findStringInsensitive(QStringView haystack, qsizetype from, char16_t needle) noexcept;
[[nodiscard]] inline qsizetype findString(QStringView str, qsizetype from, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1StringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp
index 67c75d708e..9fc3318d71 100644
--- a/src/corelib/text/qstringconverter.cpp
+++ b/src/corelib/text/qstringconverter.cpp
@@ -1910,20 +1910,37 @@ const QStringConverter::Interface QStringConverter::encodingInterfaces[QStringCo
};
// match names case insensitive and skipping '-' and '_'
-static bool nameMatch(const char *a, const char *b)
+static bool nameMatch_impl(const char *a, QLatin1StringView rhs)
{
+ const char *b = rhs.data();
+ const char *b_end = rhs.end();
do {
while (*a == '-' || *a == '_')
++a;
- while (*b == '-' || *b == '_')
+ while (b != b_end && (*b == '-' || *b == '_'))
++b;
- if (!*a && !*b) // end of both strings
+ if (!*a && b == b_end) // end of both strings
return true;
} while (QtMiscUtils::toAsciiLower(*a++) == QtMiscUtils::toAsciiLower(*b++));
return false;
}
+static bool nameMatch_impl(const char *a, QUtf8StringView b)
+{
+ return nameMatch_impl(a, QLatin1StringView{QByteArrayView{b}});
+}
+
+static bool nameMatch_impl(const char *a, QStringView b)
+{
+ return nameMatch_impl(a, QLatin1StringView{b.toString().toLatin1()}); // ### optimize
+}
+
+static bool nameMatch(const char *a, QAnyStringView b)
+{
+ return b.visit([a](auto b) { return nameMatch_impl(a, b); });
+}
+
/*!
\fn constexpr QStringConverter::QStringConverter()
@@ -2129,6 +2146,10 @@ struct QStringConverterICU : QStringConverter
return conv;
}
+ static const QStringConverter::Interface *
+ make_icu_converter(QStringConverterBase::State *state, QAnyStringView name)
+ { return make_icu_converter(state, name.toString().toLatin1().constData()); } // ### optimize
+
static const QStringConverter::Interface *make_icu_converter(
QStringConverterBase::State *state,
const char *name)
@@ -2166,7 +2187,7 @@ struct QStringConverterICU : QStringConverter
/*!
\internal
*/
-QStringConverter::QStringConverter(const char *name, Flags f)
+QStringConverter::QStringConverter(QAnyStringView name, Flags f)
: iface(nullptr), state(f)
{
auto e = encodingForName(name);
@@ -2237,17 +2258,18 @@ const char *QStringConverter::name() const noexcept
the QStringConverter constructor when Qt is built with ICU, if ICU provides a
converter with the given name.
- \a name is expected to be UTF-8 encoded.
+ \note In Qt versions prior to 6.8, this function took only a \c{const char *},
+ which was expected to be UTF-8-encoded.
*/
-std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(const char *name) noexcept
+std::optional<QStringConverter::Encoding> QStringConverter::encodingForName(QAnyStringView name) noexcept
{
- if (!name)
+ if (name.isEmpty())
return std::nullopt;
for (qsizetype i = 0; i < LastEncoding + 1; ++i) {
if (nameMatch(encodingInterfaces[i].name, name))
return QStringConverter::Encoding(i);
}
- if (nameMatch(name, "latin1"))
+ if (nameMatch("latin1", name))
return QStringConverter::Latin1;
return std::nullopt;
}
@@ -2501,20 +2523,13 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
*/
/*!
- \fn constexpr QStringEncoder::QStringEncoder(const char *name, Flags flags = Flag::Default)
+ \fn QStringEncoder::QStringEncoder(QAnyStringView name, Flags flags = Flag::Default)
Creates an encoder object using \a name and \a flags.
If \a name is not the name of a known encoding an invalid converter will get created.
- \sa isValid()
-*/
-
-/*!
- \fn constexpr QStringEncoder::QStringEncoder(const QString &name, Flags flags = Flag::Default)
- \since 6.8
-
- Creates an encoder object using \a name and \a flags.
- If \a name is not the name of a known encoding an invalid converter will get created.
+ \note In Qt versions prior to 6.8, this function took only a \c{const char *},
+ which was expected to be UTF-8-encoded.
\sa isValid()
*/
@@ -2602,20 +2617,13 @@ const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e)
*/
/*!
- \fn constexpr QStringDecoder::QStringDecoder(const char *name, Flags flags = Flag::Default)
+ \fn QStringDecoder::QStringDecoder(QAnyStringView name, Flags flags = Flag::Default)
Creates an decoder object using \a name and \a flags.
If \a name is not the name of a known encoding an invalid converter will get created.
- \sa isValid()
-*/
-
-/*!
- \fn constexpr QStringDecoder::QStringDecoder(const QString &name, Flags flags = Flag::Default)
- \since 6.8
-
- Creates an decoder object using \a name and \a flags.
- If \a name is not the name of a known encoding an invalid converter will get created.
+ \note In Qt versions prior to 6.8, this function took only a \c{const char *},
+ which was expected to be UTF-8-encoded.
\sa isValid()
*/
diff --git a/src/corelib/text/qstringconverter.h b/src/corelib/text/qstringconverter.h
index 40791f8e26..5df6f84e06 100644
--- a/src/corelib/text/qstringconverter.h
+++ b/src/corelib/text/qstringconverter.h
@@ -30,12 +30,9 @@ public:
constexpr explicit QStringEncoder(Encoding encoding, Flags flags = Flag::Default)
: QStringConverter(encoding, flags)
{}
- explicit QStringEncoder(const char *name, Flags flags = Flag::Default)
+ explicit QStringEncoder(QAnyStringView name, Flags flags = Flag::Default)
: QStringConverter(name, flags)
{}
- Q_WEAK_OVERLOAD explicit QStringEncoder(const QString &name, Flags flags = Flag::Default)
- : QStringEncoder(name.toLatin1().constData(), flags)
- {}
template<typename T>
struct DecodedData
@@ -95,12 +92,9 @@ public:
constexpr QStringDecoder() noexcept
: QStringConverter()
{}
- explicit QStringDecoder(const char *name, Flags f = Flag::Default)
+ explicit QStringDecoder(QAnyStringView name, Flags f = Flag::Default)
: QStringConverter(name, f)
{}
- Q_WEAK_OVERLOAD explicit QStringDecoder(const QString &name, Flags f = Flag::Default)
- : QStringDecoder(name.toLatin1().constData(), f)
- {}
template<typename T>
struct EncodedData
diff --git a/src/corelib/text/qstringconverter_base.h b/src/corelib/text/qstringconverter_base.h
index d6b6fcb484..a78c64a96b 100644
--- a/src/corelib/text/qstringconverter_base.h
+++ b/src/corelib/text/qstringconverter_base.h
@@ -14,6 +14,7 @@
#include <QtCore/qglobal.h> // QT_{BEGIN,END}_NAMESPACE
#include <QtCore/qflags.h> // Q_DECLARE_FLAGS
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qstringfwd.h>
#include <cstring>
@@ -137,7 +138,10 @@ protected:
constexpr explicit QStringConverter(const Interface *i) noexcept
: iface(i)
{}
+#if QT_CORE_REMOVED_SINCE(6, 8)
Q_CORE_EXPORT explicit QStringConverter(const char *name, Flags f);
+#endif
+ Q_CORE_EXPORT explicit QStringConverter(QAnyStringView name, Flags f);
~QStringConverter() = default;
@@ -156,7 +160,10 @@ public:
Q_CORE_EXPORT const char *name() const noexcept;
+#if QT_CORE_REMOVED_SINCE(6, 8)
Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept;
+#endif
+ Q_CORE_EXPORT static std::optional<Encoding> encodingForName(QAnyStringView name) noexcept;
Q_CORE_EXPORT static const char *nameForEncoding(Encoding e);
Q_CORE_EXPORT static std::optional<Encoding>
encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept;
diff --git a/src/corelib/text/qstringconverter_p.h b/src/corelib/text/qstringconverter_p.h
index e68ffb2bb0..5c530cf1bd 100644
--- a/src/corelib/text/qstringconverter_p.h
+++ b/src/corelib/text/qstringconverter_p.h
@@ -52,6 +52,7 @@ struct QLatin1
static char *convertFromUnicode(char *out, QStringView in, QStringConverter::State *state) noexcept;
// Defined in qstring.cpp
+ Q_CORE_EXPORT
static char *convertFromUnicode(char *out, QStringView in) noexcept;
};
diff --git a/src/corelib/text/qutf8stringview.h b/src/corelib/text/qutf8stringview.h
index fe105e283e..cc9ce50455 100644
--- a/src/corelib/text/qutf8stringview.h
+++ b/src/corelib/text/qutf8stringview.h
@@ -414,7 +414,8 @@ private:
qsizetype m_size;
};
-constexpr QByteArrayView::QByteArrayView(QUtf8StringView v) noexcept
+template <bool UseChar8T>
+constexpr QByteArrayView::QByteArrayView(QBasicUtf8StringView<UseChar8T> v) noexcept
: QByteArrayView(v.data(), v.size())
{}