Warning, file /include/QtCore/qanystringview.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004 #ifndef QANYSTRINGVIEW_H
0005 #define QANYSTRINGVIEW_H
0006
0007 #include <QtCore/qlatin1stringview.h>
0008 #include <QtCore/qstringview.h>
0009 #include <QtCore/qutf8stringview.h>
0010
0011 #ifdef __cpp_impl_three_way_comparison
0012 #include <compare>
0013 #endif
0014 #include <QtCore/q20type_traits.h>
0015 #include <limits>
0016
0017 class tst_QAnyStringView;
0018
0019 QT_BEGIN_NAMESPACE
0020
0021 namespace QtPrivate {
0022
0023 template <typename Tag, typename Result>
0024 struct wrapped { using type = Result; };
0025
0026 template <typename Tag, typename Result>
0027 using wrapped_t = typename wrapped<Tag, Result>::type;
0028
0029 }
0030
0031 class QAnyStringView
0032 {
0033 public:
0034 typedef qptrdiff difference_type;
0035 typedef qsizetype size_type;
0036 private:
0037 static constexpr size_t SizeMask = (std::numeric_limits<size_t>::max)() / 4;
0038 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
0039 static constexpr int SizeShift = 2;
0040 static constexpr size_t Latin1Flag = 1;
0041 #else
0042 static constexpr int SizeShift = 0;
0043 static constexpr size_t Latin1Flag = SizeMask + 1;
0044 #endif
0045 static constexpr size_t TwoByteCodePointFlag = Latin1Flag << 1;
0046 static constexpr size_t TypeMask = ~(SizeMask << SizeShift);
0047 static_assert(TypeMask == (Latin1Flag|TwoByteCodePointFlag));
0048
0049
0050
0051
0052
0053
0054
0055
0056 enum Tag : size_t {
0057 Utf8 = 0,
0058 Latin1 = Latin1Flag,
0059 Utf16 = TwoByteCodePointFlag,
0060 Unused = TypeMask,
0061 };
0062
0063 template <typename Char>
0064 using is_compatible_char = std::disjunction<
0065 QtPrivate::IsCompatibleCharType<Char>,
0066 QtPrivate::IsCompatibleChar8Type<Char>
0067 >;
0068
0069 template <typename Char>
0070 using if_compatible_char = std::enable_if_t<is_compatible_char<Char>::value, bool>;
0071
0072 template <typename Pointer>
0073 using if_compatible_pointer = std::enable_if_t<std::disjunction_v<
0074 QtPrivate::IsCompatiblePointer<Pointer>,
0075 QtPrivate::IsCompatiblePointer8<Pointer>
0076 >, bool>;
0077
0078
0079 template <typename T>
0080 using if_compatible_container = std::enable_if_t<std::disjunction_v<
0081 QtPrivate::IsContainerCompatibleWithQStringView<T>,
0082 QtPrivate::IsContainerCompatibleWithQUtf8StringView<T>
0083 >, bool>;
0084
0085 template <typename QStringOrQByteArray, typename T>
0086 using if_convertible_to = std::enable_if_t<std::conjunction_v<
0087
0088 std::negation<std::disjunction<
0089 std::is_same<q20::remove_cvref_t<T>, QAnyStringView::Tag>,
0090 std::is_same<q20::remove_cvref_t<T>, QAnyStringView>,
0091 std::is_pointer<std::decay_t<T>>,
0092 is_compatible_char<T>,
0093 std::is_same<q20::remove_cvref_t<T>, QByteArray>,
0094 std::is_same<q20::remove_cvref_t<T>, QString>
0095 >>,
0096
0097 std::is_convertible<T, QStringOrQByteArray>
0098 >, bool>;
0099
0100
0101 static_assert(QtPrivate::IsContainerCompatibleWithQStringView<QAnyStringView>::value == false);
0102 static_assert(QtPrivate::IsContainerCompatibleWithQUtf8StringView<QAnyStringView>::value == false);
0103
0104 template<typename Char>
0105 static constexpr bool isAsciiOnlyCharsAtCompileTime(Char *str, qsizetype sz) noexcept
0106 {
0107
0108 if (!q20::is_constant_evaluated())
0109 return false;
0110 if constexpr (sizeof(Char) != sizeof(char)) {
0111 Q_UNUSED(str);
0112 Q_UNUSED(sz);
0113 return false;
0114 } else {
0115 for (qsizetype i = 0; i < sz; ++i) {
0116 if (uchar(str[i]) > 0x7f)
0117 return false;
0118 }
0119 return true;
0120 }
0121 }
0122
0123 template<typename Char>
0124 static constexpr std::size_t encodeType(const Char *str, qsizetype sz) noexcept
0125 {
0126
0127 Q_ASSERT(sz >= 0);
0128 Q_ASSERT(sz <= qsizetype(SizeMask));
0129 Q_ASSERT(str || !sz);
0130 return (std::size_t(sz) << SizeShift)
0131 | uint(sizeof(Char) == sizeof(char16_t)) * Tag::Utf16
0132 | uint(isAsciiOnlyCharsAtCompileTime(str, sz)) * Tag::Latin1;
0133 }
0134
0135 template <typename Char>
0136 static constexpr qsizetype lengthHelperPointer(const Char *str) noexcept
0137 {
0138 if (q20::is_constant_evaluated())
0139 return qsizetype(std::char_traits<Char>::length(str));
0140 if constexpr (sizeof(Char) == sizeof(char16_t))
0141 return QtPrivate::qustrlen(reinterpret_cast<const char16_t*>(str));
0142 else
0143 return qsizetype(strlen(reinterpret_cast<const char*>(str)));
0144 }
0145
0146 static QChar toQChar(char ch) noexcept { return toQChar(QLatin1Char{ch}); }
0147 static QChar toQChar(QChar ch) noexcept { return ch; }
0148 static QChar toQChar(QLatin1Char ch) noexcept { return ch; }
0149
0150 struct QCharContainer {
0151 explicit QCharContainer() = default;
0152 QChar ch;
0153 };
0154
0155 explicit constexpr QAnyStringView(const void *d, qsizetype n, std::size_t sizeAndType) noexcept
0156 : m_data{d}, m_size{std::size_t(n) | (sizeAndType & TypeMask)} {}
0157 public:
0158 constexpr QAnyStringView() noexcept
0159 : m_data{nullptr}, m_size{0} {}
0160 constexpr QAnyStringView(std::nullptr_t) noexcept
0161 : QAnyStringView() {}
0162
0163 template <typename Char, if_compatible_char<Char> = true>
0164 constexpr QAnyStringView(const Char *str, qsizetype len)
0165 : m_data{str}, m_size{encodeType<Char>(str, len)}
0166 {
0167 }
0168
0169 template <typename Char, if_compatible_char<Char> = true>
0170 constexpr QAnyStringView(const Char *f, const Char *l)
0171 : QAnyStringView(f, l - f) {}
0172
0173 #ifdef Q_QDOC
0174 template <typename Char, size_t N>
0175 constexpr QAnyStringView(const Char (&array)[N]) noexcept;
0176
0177 template <typename Char>
0178 constexpr QAnyStringView(const Char *str) noexcept;
0179 #else
0180
0181 template <typename Pointer, if_compatible_pointer<Pointer> = true>
0182 constexpr QAnyStringView(const Pointer &str) noexcept
0183 : QAnyStringView{str, str ? lengthHelperPointer(str) : 0} {}
0184 #endif
0185
0186
0187 inline QAnyStringView(const QByteArray &str) noexcept;
0188 inline QAnyStringView(const QString &str) noexcept;
0189 inline constexpr QAnyStringView(QLatin1StringView str) noexcept;
0190
0191 template <typename Container, if_compatible_container<Container> = true>
0192 constexpr Q_ALWAYS_INLINE QAnyStringView(const Container &c) noexcept
0193 : QAnyStringView(std::data(c), QtPrivate::lengthHelperContainer(c)) {}
0194
0195 template <typename Container, if_convertible_to<QString, Container> = true>
0196 constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QString> &&capacity = {})
0197
0198 : QAnyStringView(capacity = std::forward<Container>(c)) {}
0199
0200 template <typename Container, if_convertible_to<QByteArray, Container> = true>
0201 constexpr QAnyStringView(Container &&c, QtPrivate::wrapped_t<Container, QByteArray> &&capacity = {})
0202
0203 : QAnyStringView(capacity = std::forward<Container>(c)) {}
0204 template <typename Char, if_compatible_char<Char> = true>
0205 constexpr QAnyStringView(const Char &c) noexcept
0206 : QAnyStringView{&c, 1} {}
0207 template <typename Char, if_convertible_to<QChar, Char> = true>
0208 constexpr QAnyStringView(Char ch, QCharContainer &&capacity = QCharContainer()) noexcept
0209 : QAnyStringView{&(capacity.ch = ch), 1} {}
0210
0211 template <typename Char, typename Container = decltype(QChar::fromUcs4(U'x')),
0212 std::enable_if_t<std::is_same_v<Char, char32_t>, bool> = true>
0213 constexpr QAnyStringView(Char c, Container &&capacity = {}) noexcept
0214 : QAnyStringView(capacity = QChar::fromUcs4(c)) {}
0215
0216 constexpr QAnyStringView(QStringView v) noexcept
0217 : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {}
0218
0219 template <bool UseChar8T>
0220 constexpr QAnyStringView(QBasicUtf8StringView<UseChar8T> v) noexcept
0221 : QAnyStringView(std::data(v), QtPrivate::lengthHelperContainer(v)) {}
0222
0223 template <typename Char, size_t Size, if_compatible_char<Char> = true>
0224 [[nodiscard]] constexpr static QAnyStringView fromArray(const Char (&string)[Size]) noexcept
0225 { return QAnyStringView(string, Size); }
0226
0227
0228 template <typename Visitor>
0229 inline constexpr decltype(auto) visit(Visitor &&v) const;
0230
0231 [[nodiscard]]
0232 constexpr QAnyStringView mid(qsizetype pos, qsizetype n = -1) const
0233 {
0234 using namespace QtPrivate;
0235 auto result = QContainerImplHelper::mid(size(), &pos, &n);
0236 return result == QContainerImplHelper::Null ? QAnyStringView() : sliced(pos, n);
0237 }
0238 [[nodiscard]]
0239 constexpr QAnyStringView left(qsizetype n) const
0240 {
0241 if (size_t(n) >= size_t(size()))
0242 n = size();
0243 return sliced(0, n);
0244 }
0245 [[nodiscard]]
0246 constexpr QAnyStringView right(qsizetype n) const
0247 {
0248 if (size_t(n) >= size_t(size()))
0249 n = size();
0250 return sliced(size() - n, n);
0251 }
0252
0253 [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos) const
0254 { verify(pos, 0); auto r = *this; r.advanceData(pos); r.setSize(size() - pos); return r; }
0255 [[nodiscard]] constexpr QAnyStringView sliced(qsizetype pos, qsizetype n) const
0256 { verify(pos, n); auto r = *this; r.advanceData(pos); r.setSize(n); return r; }
0257 [[nodiscard]] constexpr QAnyStringView first(qsizetype n) const
0258 { verify(0, n); return sliced(0, n); }
0259 [[nodiscard]] constexpr QAnyStringView last(qsizetype n) const
0260 { verify(0, n); return sliced(size() - n, n); }
0261 [[nodiscard]] constexpr QAnyStringView chopped(qsizetype n) const
0262 { verify(0, n); return sliced(0, size() - n); }
0263
0264 constexpr void truncate(qsizetype n)
0265 { verify(0, n); setSize(n); }
0266 constexpr void chop(qsizetype n)
0267 { verify(0, n); setSize(size() - n); }
0268
0269
0270 [[nodiscard]] inline QString toString() const;
0271
0272 [[nodiscard]] constexpr qsizetype size() const noexcept
0273 { return qsizetype((m_size >> SizeShift) & SizeMask); }
0274 [[nodiscard]] constexpr const void *data() const noexcept { return m_data; }
0275
0276 [[nodiscard]] Q_CORE_EXPORT static int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
0277 [[nodiscard]] Q_CORE_EXPORT static bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept;
0278
0279 static constexpr inline bool detects_US_ASCII_at_compile_time =
0280 #ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
0281 true
0282 #else
0283 false
0284 #endif
0285 ;
0286
0287
0288
0289
0290 [[nodiscard]] constexpr QChar front() const;
0291 [[nodiscard]] constexpr QChar back() const;
0292 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0293 [[nodiscard]] constexpr qsizetype size_bytes() const noexcept
0294 { return size() * charSize(); }
0295
0296
0297
0298
0299 [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0300 [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0301 [[nodiscard]] constexpr qsizetype length() const noexcept
0302 { return size(); }
0303
0304 private:
0305 [[nodiscard]] friend inline bool operator==(QAnyStringView lhs, QAnyStringView rhs) noexcept
0306 { return QAnyStringView::equal(lhs, rhs); }
0307 [[nodiscard]] friend inline bool operator!=(QAnyStringView lhs, QAnyStringView rhs) noexcept
0308 { return !QAnyStringView::equal(lhs, rhs); }
0309
0310 #if defined(__cpp_impl_three_way_comparison) && !defined(Q_QDOC)
0311 [[nodiscard]] friend inline auto operator<=>(QAnyStringView lhs, QAnyStringView rhs) noexcept
0312 { return QAnyStringView::compare(lhs, rhs) <=> 0; }
0313 #else
0314 [[nodiscard]] friend inline bool operator<=(QAnyStringView lhs, QAnyStringView rhs) noexcept
0315 { return QAnyStringView::compare(lhs, rhs) <= 0; }
0316 [[nodiscard]] friend inline bool operator>=(QAnyStringView lhs, QAnyStringView rhs) noexcept
0317 { return QAnyStringView::compare(lhs, rhs) >= 0; }
0318 [[nodiscard]] friend inline bool operator<(QAnyStringView lhs, QAnyStringView rhs) noexcept
0319 { return QAnyStringView::compare(lhs, rhs) < 0; }
0320 [[nodiscard]] friend inline bool operator>(QAnyStringView lhs, QAnyStringView rhs) noexcept
0321 { return QAnyStringView::compare(lhs, rhs) > 0; }
0322 #endif
0323
0324 #ifndef QT_NO_DEBUG_STREAM
0325 Q_CORE_EXPORT friend QDebug operator<<(QDebug d, QAnyStringView s);
0326 #endif
0327
0328 [[nodiscard]] constexpr Tag tag() const noexcept { return Tag{m_size & TypeMask}; }
0329 [[nodiscard]] constexpr bool isUtf16() const noexcept { return tag() == Tag::Utf16; }
0330 [[nodiscard]] constexpr bool isUtf8() const noexcept { return tag() == Tag::Utf8; }
0331 [[nodiscard]] constexpr bool isLatin1() const noexcept { return tag() == Tag::Latin1; }
0332 [[nodiscard]] constexpr QStringView asStringView() const
0333 { return Q_ASSERT(isUtf16()), QStringView{m_data_utf16, size()}; }
0334 [[nodiscard]] constexpr q_no_char8_t::QUtf8StringView asUtf8StringView() const
0335 { return Q_ASSERT(isUtf8()), q_no_char8_t::QUtf8StringView{m_data_utf8, size()}; }
0336 [[nodiscard]] inline constexpr QLatin1StringView asLatin1StringView() const;
0337 [[nodiscard]] constexpr size_t charSize() const noexcept { return isUtf16() ? 2 : 1; }
0338 constexpr void setSize(qsizetype sz) noexcept { m_size = size_t(sz) | tag(); }
0339 constexpr void advanceData(qsizetype delta) noexcept
0340 { m_data_utf8 += delta * charSize(); }
0341 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0342 [[maybe_unused]] qsizetype n = 1) const
0343 {
0344 Q_ASSERT(pos >= 0);
0345 Q_ASSERT(pos <= size());
0346 Q_ASSERT(n >= 0);
0347 Q_ASSERT(n <= size() - pos);
0348 }
0349 union {
0350 const void *m_data;
0351 const char *m_data_utf8;
0352 const char16_t *m_data_utf16;
0353 };
0354 size_t m_size;
0355 friend class ::tst_QAnyStringView;
0356 };
0357 Q_DECLARE_TYPEINFO(QAnyStringView, Q_PRIMITIVE_TYPE);
0358
0359 template <typename QStringLike, std::enable_if_t<std::disjunction_v<
0360 std::is_same<QStringLike, QString>,
0361 std::is_same<QStringLike, QByteArray>
0362 >, bool> = true>
0363 [[nodiscard]] inline QAnyStringView qToAnyStringViewIgnoringNull(const QStringLike &s) noexcept
0364 { return QAnyStringView(s.data(), s.size()); }
0365
0366 QT_END_NAMESPACE
0367
0368 #endif