summaryrefslogtreecommitdiffstats
path: root/src/corelib/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text')
-rw-r--r--src/corelib/text/qanystringview.h23
-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.h25
-rw-r--r--src/corelib/text/qchar.cpp51
-rw-r--r--src/corelib/text/qchar.h14
-rw-r--r--src/corelib/text/qlocale.cpp5
-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/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/qstringview.h2
-rw-r--r--src/corelib/text/qutf8stringview.h12
20 files changed, 342 insertions, 291 deletions
diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h
index 01efd83743..075d64679c 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>
>>,
@@ -133,7 +137,7 @@ private:
static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
{
if (q20::is_constant_evaluated())
- return qsizetype(std::char_traits<Char>::length(str));
+ return QtPrivate::lengthHelperPointer(str);
if constexpr (sizeof(Char) == sizeof(char16_t))
return QtPrivate::qustrlen(reinterpret_cast<const char16_t*>(str));
else
@@ -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..dea0e6cbe8 100644
--- a/src/corelib/text/qbytearrayview.h
+++ b/src/corelib/text/qbytearrayview.h
@@ -68,7 +68,15 @@ struct IsContainerCompatibleWithQByteArrayView<T, std::enable_if_t<
template <typename Char>
static constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
{
- return qsizetype(std::char_traits<Char>::length(data));
+ // std::char_traits can only be used with one of the regular char types
+ // (char, char16_t, wchar_t, but not uchar or QChar), so we roll the loop
+ // out by ourselves.
+ qsizetype i = 0;
+ if (!data)
+ return i;
+ while (data[i] != Char(0))
+ ++i;
+ return i;
}
} // namespace QtPrivate
@@ -169,7 +177,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 +410,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/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_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/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/qstringview.h b/src/corelib/text/qstringview.h
index ab97d834d3..2ad245caa3 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -108,7 +108,7 @@ private:
static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
{
if (q20::is_constant_evaluated())
- return std::char_traits<Char>::length(str);
+ return QtPrivate::lengthHelperPointer(str);
return QtPrivate::qustrlen(reinterpret_cast<const char16_t *>(str));
}
static qsizetype lengthHelperPointer(const QChar *str) noexcept
diff --git a/src/corelib/text/qutf8stringview.h b/src/corelib/text/qutf8stringview.h
index fe105e283e..7ae06c0ec4 100644
--- a/src/corelib/text/qutf8stringview.h
+++ b/src/corelib/text/qutf8stringview.h
@@ -134,14 +134,12 @@ private:
return qsizetype(std::size(c));
}
- // Note: Do not replace with std::size(const Char (&)[N]), cause the result
+ // Note: Do not replace with std::size(const Char (&)[N]), because the result
// will be of by one.
template <typename Char, size_t N>
static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept
{
- const auto it = std::char_traits<Char>::find(str, N, Char(0));
- const auto end = it ? it : std::next(str, N);
- return qsizetype(std::distance(str, end));
+ return QtPrivate::lengthHelperContainer(str);
}
template <typename Char>
@@ -174,8 +172,7 @@ public:
#else
template <typename Pointer, if_compatible_pointer<Pointer> = true>
constexpr QBasicUtf8StringView(const Pointer &str) noexcept
- : QBasicUtf8StringView(str,
- str ? std::char_traits<std::remove_cv_t<std::remove_pointer_t<Pointer>>>::length(str) : 0) {}
+ : QBasicUtf8StringView(str, QtPrivate::lengthHelperPointer(str)) {}
#endif
#ifdef Q_QDOC
@@ -414,7 +411,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())
{}