Warning, file /include/QtCore/qutf8stringview.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 #ifndef QUTF8STRINGVIEW_H
0004 #define QUTF8STRINGVIEW_H
0005
0006 #if 0
0007 #pragma qt_class(QUtf8StringView)
0008 #endif
0009
0010 #include <QtCore/qstringalgorithms.h>
0011 #include <QtCore/qstringfwd.h>
0012 #include <QtCore/qarraydata.h> // for QContainerImplHelper
0013 #include <QtCore/qbytearrayview.h>
0014
0015 #include <string>
0016 #include <string_view>
0017 #include <QtCore/q20type_traits.h>
0018
0019 QT_BEGIN_NAMESPACE
0020
0021 namespace QtPrivate {
0022 template <typename Char>
0023 using IsCompatibleChar8TypeHelper = std::disjunction<
0024 #ifdef __cpp_char8_t
0025 std::is_same<Char, char8_t>,
0026 #endif
0027 std::is_same<Char, char>,
0028 std::is_same<Char, uchar>,
0029 std::is_same<Char, signed char>
0030 >;
0031 template <typename Char>
0032 using IsCompatibleChar8Type
0033 = IsCompatibleChar8TypeHelper<q20::remove_cvref_t<Char>>;
0034
0035 template <typename Pointer>
0036 struct IsCompatiblePointer8Helper : std::false_type {};
0037 template <typename Char>
0038 struct IsCompatiblePointer8Helper<Char*>
0039 : IsCompatibleChar8Type<Char> {};
0040 template <typename Pointer>
0041 using IsCompatiblePointer8
0042 = IsCompatiblePointer8Helper<q20::remove_cvref_t<Pointer>>;
0043
0044 template <typename T, typename Enable = void>
0045 struct IsContainerCompatibleWithQUtf8StringView : std::false_type {};
0046
0047 template <typename T>
0048 struct IsContainerCompatibleWithQUtf8StringView<T, std::enable_if_t<std::conjunction_v<
0049
0050 IsCompatiblePointer8<decltype(std::data(std::declval<const T &>()))>,
0051
0052 std::is_convertible<
0053 decltype(std::size(std::declval<const T &>())),
0054 qsizetype
0055 >,
0056
0057 IsCompatibleChar8Type<typename std::iterator_traits<
0058 decltype(std::begin(std::declval<const T &>()))>::value_type
0059 >,
0060 std::is_convertible<
0061 decltype( std::begin(std::declval<const T &>()) != std::end(std::declval<const T &>()) ),
0062 bool
0063 >,
0064
0065
0066 std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
0067
0068
0069 std::negation<std::is_same<std::decay_t<T>, QLatin1StringView>>,
0070
0071
0072 std::negation<std::disjunction<
0073 std::is_same<std::decay_t<T>, QBasicUtf8StringView<true>>,
0074 std::is_same<std::decay_t<T>, QBasicUtf8StringView<false>>
0075 >>
0076 >>> : std::true_type {};
0077
0078 struct hide_char8_t {
0079 #ifdef __cpp_char8_t
0080 using type = char8_t;
0081 #endif
0082 };
0083
0084 struct wrap_char { using type = char; };
0085
0086 }
0087
0088 #ifdef Q_QDOC
0089 #define QBasicUtf8StringView QUtf8StringView
0090 #else
0091 template <bool UseChar8T>
0092 #endif
0093 class QBasicUtf8StringView
0094 {
0095 public:
0096 #ifndef Q_QDOC
0097 using storage_type = typename std::conditional<UseChar8T,
0098 QtPrivate::hide_char8_t,
0099 QtPrivate::wrap_char
0100 >::type::type;
0101 #else
0102 using storage_type = typename QtPrivate::hide_char8_t;
0103 #endif
0104 typedef const storage_type value_type;
0105 typedef qptrdiff difference_type;
0106 typedef qsizetype size_type;
0107 typedef value_type &reference;
0108 typedef value_type &const_reference;
0109 typedef value_type *pointer;
0110 typedef value_type *const_pointer;
0111
0112 typedef pointer iterator;
0113 typedef const_pointer const_iterator;
0114 typedef std::reverse_iterator<iterator> reverse_iterator;
0115 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0116
0117 private:
0118 template <typename Char>
0119 using if_compatible_char = std::enable_if_t<QtPrivate::IsCompatibleChar8Type<Char>::value, bool>;
0120
0121 template <typename Pointer>
0122 using if_compatible_pointer = std::enable_if_t<QtPrivate::IsCompatiblePointer8<Pointer>::value, bool>;
0123
0124 template <typename T>
0125 using if_compatible_qstring_like = std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
0126
0127 template <typename T>
0128 using if_compatible_container = std::enable_if_t<QtPrivate::IsContainerCompatibleWithQUtf8StringView<T>::value, bool>;
0129
0130 template <typename Container>
0131 static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
0132 {
0133 return qsizetype(std::size(c));
0134 }
0135
0136
0137
0138 template <typename Char, size_t N>
0139 static constexpr qsizetype lengthHelperContainer(const Char (&str)[N]) noexcept
0140 {
0141 const auto it = std::char_traits<Char>::find(str, N, Char(0));
0142 const auto end = it ? it : std::next(str, N);
0143 return qsizetype(std::distance(str, end));
0144 }
0145
0146 template <typename Char>
0147 static const storage_type *castHelper(const Char *str) noexcept
0148 { return reinterpret_cast<const storage_type*>(str); }
0149 static constexpr const storage_type *castHelper(const storage_type *str) noexcept
0150 { return str; }
0151
0152 public:
0153 constexpr QBasicUtf8StringView() noexcept
0154 : m_data(nullptr), m_size(0) {}
0155 constexpr QBasicUtf8StringView(std::nullptr_t) noexcept
0156 : QBasicUtf8StringView() {}
0157
0158 template <typename Char, if_compatible_char<Char> = true>
0159 constexpr QBasicUtf8StringView(const Char *str, qsizetype len)
0160 : m_data(castHelper(str)),
0161 m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)) {}
0162
0163 template <typename Char, if_compatible_char<Char> = true>
0164 constexpr QBasicUtf8StringView(const Char *f, const Char *l)
0165 : QBasicUtf8StringView(f, l - f) {}
0166
0167 #ifdef Q_QDOC
0168 template <typename Char, size_t N>
0169 constexpr QBasicUtf8StringView(const Char (&array)[N]) noexcept;
0170
0171 template <typename Char>
0172 constexpr QBasicUtf8StringView(const Char *str) noexcept;
0173 #else
0174 template <typename Pointer, if_compatible_pointer<Pointer> = true>
0175 constexpr QBasicUtf8StringView(const Pointer &str) noexcept
0176 : QBasicUtf8StringView(str,
0177 str ? std::char_traits<std::remove_cv_t<std::remove_pointer_t<Pointer>>>::length(str) : 0) {}
0178 #endif
0179
0180 #ifdef Q_QDOC
0181 QBasicUtf8StringView(const QByteArray &str) noexcept;
0182 constexpr QBasicUtf8StringView(const storage_type *d, qsizetype n) noexcept {};
0183 #else
0184 template <typename String, if_compatible_qstring_like<String> = true>
0185 QBasicUtf8StringView(const String &str) noexcept
0186 : QBasicUtf8StringView(str.isNull() ? nullptr : str.data(), qsizetype(str.size())) {}
0187 #endif
0188
0189 template <typename Container, if_compatible_container<Container> = true>
0190 constexpr QBasicUtf8StringView(const Container &c) noexcept
0191 : QBasicUtf8StringView(std::data(c), lengthHelperContainer(c)) {}
0192
0193 #if defined(__cpp_char8_t) && !defined(Q_QDOC)
0194 constexpr QBasicUtf8StringView(QBasicUtf8StringView<!UseChar8T> other)
0195 : QBasicUtf8StringView(other.data(), other.size()) {}
0196 #endif
0197
0198 template <typename Char, size_t Size, if_compatible_char<Char> = true>
0199 [[nodiscard]] constexpr static QBasicUtf8StringView fromArray(const Char (&string)[Size]) noexcept
0200 { return QBasicUtf8StringView(string, Size); }
0201
0202 [[nodiscard]] inline QString toString() const;
0203
0204 [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
0205 [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
0206 #ifdef __cpp_char8_t
0207 [[nodiscard]] const char8_t *utf8() const noexcept { return reinterpret_cast<const char8_t*>(m_data); }
0208 #endif
0209
0210 [[nodiscard]] constexpr storage_type operator[](qsizetype n) const
0211 { verify(n, 1); return m_data[n]; }
0212
0213
0214
0215
0216
0217 [[nodiscard]] constexpr storage_type at(qsizetype n) const { return (*this)[n]; }
0218
0219 [[nodiscard]]
0220 constexpr QBasicUtf8StringView mid(qsizetype pos, qsizetype n = -1) const
0221 {
0222 using namespace QtPrivate;
0223 auto result = QContainerImplHelper::mid(size(), &pos, &n);
0224 return result == QContainerImplHelper::Null ? QBasicUtf8StringView() : QBasicUtf8StringView(m_data + pos, n);
0225 }
0226 [[nodiscard]]
0227 constexpr QBasicUtf8StringView left(qsizetype n) const
0228 {
0229 if (size_t(n) >= size_t(size()))
0230 n = size();
0231 return QBasicUtf8StringView(m_data, n);
0232 }
0233 [[nodiscard]]
0234 constexpr QBasicUtf8StringView right(qsizetype n) const
0235 {
0236 if (size_t(n) >= size_t(size()))
0237 n = size();
0238 return QBasicUtf8StringView(m_data + m_size - n, n);
0239 }
0240
0241 [[nodiscard]] constexpr QBasicUtf8StringView sliced(qsizetype pos) const
0242 { verify(pos, 0); return QBasicUtf8StringView{m_data + pos, m_size - pos}; }
0243 [[nodiscard]] constexpr QBasicUtf8StringView sliced(qsizetype pos, qsizetype n) const
0244 { verify(pos, n); return QBasicUtf8StringView(m_data + pos, n); }
0245 [[nodiscard]] constexpr QBasicUtf8StringView first(qsizetype n) const
0246 { verify(0, n); return sliced(0, n); }
0247 [[nodiscard]] constexpr QBasicUtf8StringView last(qsizetype n) const
0248 { verify(0, n); return sliced(m_size - n, n); }
0249 [[nodiscard]] constexpr QBasicUtf8StringView chopped(qsizetype n) const
0250 { verify(0, n); return sliced(0, m_size - n); }
0251
0252 constexpr void truncate(qsizetype n)
0253 { verify(0, n); m_size = n; }
0254 constexpr void chop(qsizetype n)
0255 { verify(0, n); m_size -= n; }
0256
0257 [[nodiscard]] inline bool isValidUtf8() const noexcept
0258 {
0259 return QByteArrayView(reinterpret_cast<const char *>(data()), size()).isValidUtf8();
0260 }
0261
0262
0263
0264
0265 [[nodiscard]] const_iterator begin() const noexcept { return data(); }
0266 [[nodiscard]] const_iterator end() const noexcept { return data() + size(); }
0267 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
0268 [[nodiscard]] const_iterator cend() const noexcept { return end(); }
0269 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
0270 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
0271 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0272 [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
0273
0274 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0275 [[nodiscard]] constexpr storage_type front() const { return Q_ASSERT(!empty()), m_data[0]; }
0276 [[nodiscard]] constexpr storage_type back() const { return Q_ASSERT(!empty()), m_data[m_size - 1]; }
0277
0278 [[nodiscard]] Q_IMPLICIT operator std::basic_string_view<storage_type>() const noexcept
0279 { return std::basic_string_view<storage_type>(data(), size_t(size())); }
0280
0281
0282
0283
0284 [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0285 [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0286 [[nodiscard]] constexpr qsizetype length() const noexcept
0287 { return size(); }
0288
0289 [[nodiscard]] int compare(QBasicUtf8StringView other,
0290 Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
0291 {
0292 return QtPrivate::compareStrings(*this, other, cs);
0293 }
0294
0295 [[nodiscard]] int compare(QStringView other,
0296 Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0297 [[nodiscard]] int compare(QLatin1StringView other,
0298 Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0299
0300 private:
0301 [[nodiscard]] static inline int compare(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0302 {
0303 return QtPrivate::compareStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
0304 QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
0305 }
0306
0307 [[nodiscard]] friend inline bool operator==(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0308 {
0309 return lhs.size() == rhs.size()
0310 && QtPrivate::equalStrings(QBasicUtf8StringView<false>(lhs.data(), lhs.size()),
0311 QBasicUtf8StringView<false>(rhs.data(), rhs.size()));
0312 }
0313 [[nodiscard]] friend inline bool operator!=(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0314 { return !operator==(lhs, rhs); }
0315
0316 #ifdef __cpp_impl_three_way_comparison
0317 [[nodiscard]] friend inline auto operator<=>(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0318 { return QBasicUtf8StringView::compare(lhs, rhs) <=> 0; }
0319 #else
0320 [[nodiscard]] friend inline bool operator<=(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0321 { return QBasicUtf8StringView::compare(lhs, rhs) <= 0; }
0322 [[nodiscard]] friend inline bool operator>=(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0323 { return QBasicUtf8StringView::compare(lhs, rhs) >= 0; }
0324 [[nodiscard]] friend inline bool operator<(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0325 { return QBasicUtf8StringView::compare(lhs, rhs) < 0; }
0326 [[nodiscard]] friend inline bool operator>(QBasicUtf8StringView lhs, QBasicUtf8StringView rhs) noexcept
0327 { return QBasicUtf8StringView::compare(lhs, rhs) > 0; }
0328 #endif
0329
0330 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0331 [[maybe_unused]] qsizetype n = 1) const
0332 {
0333 Q_ASSERT(pos >= 0);
0334 Q_ASSERT(pos <= size());
0335 Q_ASSERT(n >= 0);
0336 Q_ASSERT(n <= size() - pos);
0337 }
0338 const storage_type *m_data;
0339 qsizetype m_size;
0340 };
0341
0342 #ifdef Q_QDOC
0343 #undef QBasicUtf8StringView
0344 #else
0345 template <bool UseChar8T>
0346 Q_DECLARE_TYPEINFO_BODY(QBasicUtf8StringView<UseChar8T>, Q_PRIMITIVE_TYPE);
0347
0348 template <typename QStringLike, std::enable_if_t<std::is_same_v<QStringLike, QByteArray>, bool> = true>
0349 [[nodiscard]] inline q_no_char8_t::QUtf8StringView qToUtf8StringViewIgnoringNull(const QStringLike &s) noexcept
0350 { return q_no_char8_t::QUtf8StringView(s.data(), s.size()); }
0351 #endif
0352
0353 QT_END_NAMESPACE
0354
0355 #endif