summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstring.h
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2020-05-20 15:20:07 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-31 22:57:49 +0200
commit2c9529e158fc589c48e6b1fb61dca2133e33ac4d (patch)
treee9429715ab339d95c2ba9456bf39a894e8b41539 /src/corelib/text/qstring.h
parentf0ae973244026ca5382f05630bd799b44154d224 (diff)
Long live Q{Any,Utf8}StringView!
We need to add these two classes at the same time, because QAnyStringView makes all QUtf8StringView relational operators moot. We might want to add some later, esp. for UTF-8/UTf-8 comparisons, to avoid the pessimization that we can't early-out on size() mismatch in QAnyStringView equality operators, but that's an optimization, not a correctness issue, and can be fixed in a source-compatible way even after Qt 6 is released. To deal with the char8_t problem in C++20, make QUtf8StringView a class template out of which two UTF-8 views can be instantiated: the Qt 7 version, which depends on C++20 char8_t as value_type, and the Qt 6 version where value_type is a char. Use inline namespaces to map the QUtf8StringView identifier to one or the other, depending on the C++ version used to compile the user code. The inline namespace names must needs be a bit ugly, as their inline'ness depends on __cpp_char8_t. If we simply used q_v1/q_v2 we'd be blocking these names for Qt inline namespaces forever, because it's likely that inline'ness of other users of inline namespaces in Qt depends on things other than __cpp_char8_t. While inline'ness of namespaces is, theoretically speaking, a compile-time-only property, at least Clang warns about mixed use of inline on a given namespace, so we need to bite the bullet here. This is also the reason for the QT_BEGIN_..._NAMESPACE macros: GCC is ok with the first declaration making a namespace inline, while Clang warns upon re-opening an inline namespace as a non-inline one. [ChangeLog][QtCore][QUtf8StringView] New class. [ChangeLog][QtCore][QAnyStringView] New class. Change-Id: Ia7179760fca0e0b67d52f5accb0a62e389b17913 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/text/qstring.h')
-rw-r--r--src/corelib/text/qstring.h72
1 files changed, 71 insertions, 1 deletions
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 7fd5f86e25..7daf86a366 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -53,7 +53,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qstringliteral.h>
#include <QtCore/qstringalgorithms.h>
-#include <QtCore/qstringview.h>
+#include <QtCore/qanystringview.h>
#include <QtCore/qstringtokenizer.h>
#include <string>
@@ -81,6 +81,12 @@ namespace QtPrivate {
template <bool...B> class BoolList;
}
+// QStringAlgorithms inline functions:
+
+int QtPrivate::compareStringsUtf8(const char *lhs, qsizetype lhss, QStringView rhs, Qt::CaseSensitivity cs) noexcept
+{ return compareStrings(QUtf8StringView(lhs, lhss), rhs, cs); }
+
+
class QLatin1String
{
public:
@@ -282,6 +288,44 @@ bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexce
qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
+//
+// QAnyStringView members that require QLatin1String
+//
+
+constexpr QAnyStringView::QAnyStringView(QLatin1String str) noexcept
+ : m_data{str.data()}, m_size{size_t(str.size()) | Tag::Latin1} {}
+
+constexpr QLatin1String QAnyStringView::asLatin1StringView() const
+{
+ Q_ASSERT(isLatin1());
+ return QLatin1String{m_data_utf8, int(size())};
+}
+
+template <typename Visitor>
+constexpr decltype(auto) QAnyStringView::visit(Visitor &&v) const
+{
+ if (isUtf16())
+ return std::forward<Visitor>(v)(asStringView());
+ else if (isLatin1())
+ return std::forward<Visitor>(v)(asLatin1StringView());
+ else
+ return std::forward<Visitor>(v)(asUtf8StringView());
+}
+
+//
+// QAnyStringView members that require QAnyStringView::visit()
+//
+
+constexpr QChar QAnyStringView::front() const
+{
+ return visit([] (auto that) { return QAnyStringView::toQChar(that.front()); });
+}
+constexpr QChar QAnyStringView::back() const
+{
+ return visit([] (auto that) { return QAnyStringView::toQChar(that.back()); });
+}
+
+
class Q_CORE_EXPORT QString
{
typedef QTypedArrayData<char16_t> Data;
@@ -976,6 +1020,7 @@ QString QLatin1String::toString() const { return *this; }
//
// QStringView inline members that require QString:
//
+
QString QStringView::toString() const
{ return Q_ASSERT(size() == length()), QString(data(), length()); }
@@ -997,6 +1042,29 @@ ushort QStringView::toUShort(bool *ok, int base) const
{ return QString::toIntegral_helper<ushort>(*this, ok, base); }
//
+// QUtf8StringView inline members that require QString:
+//
+
+template <bool UseChar8T>
+QString QBasicUtf8StringView<UseChar8T>::toString() const
+{
+ Q_ASSERT(size() == int(size()));
+ return QString::fromUtf8(data(), int(size()));
+}
+
+//
+// QAnyStringView inline members that require QString:
+//
+
+QAnyStringView::QAnyStringView(const QByteArray &str) noexcept
+ : QAnyStringView{str.isNull() ? nullptr : str.data(), str.size()} {}
+QAnyStringView::QAnyStringView(const QString &str) noexcept
+ : QAnyStringView{str.isNull() ? nullptr : str.data(), str.size()} {}
+
+QString QAnyStringView::toString() const
+{ return QtPrivate::convertToQString(*this); }
+
+//
// QString inline members
//
inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.latin1(), aLatin1.size()))
@@ -1383,6 +1451,7 @@ inline bool operator> (QLatin1String lhs, QChar rhs) noexcept { return rhs <
inline bool operator<=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs < lhs); }
inline bool operator>=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs > lhs); }
+#if 0
// QStringView <> QStringView
inline bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
inline bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
@@ -1390,6 +1459,7 @@ inline bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPri
inline bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
inline bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
inline bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
+#endif
// QStringView <> QChar
inline bool operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); }