Warning, file /include/QtCore/qstringtokenizer.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
0005 #ifndef QSTRINGTOKENIZER_H
0006 #define QSTRINGTOKENIZER_H
0007
0008 #include <QtCore/qnamespace.h>
0009 #include <QtCore/qcontainerfwd.h>
0010 #include <iterator>
0011
0012 QT_BEGIN_NAMESPACE
0013
0014 template <typename, typename> class QStringBuilder;
0015
0016 class QStringTokenizerBaseBase
0017 {
0018 protected:
0019 ~QStringTokenizerBaseBase() = default;
0020 constexpr QStringTokenizerBaseBase(Qt::SplitBehavior sb, Qt::CaseSensitivity cs) noexcept
0021 : m_sb{sb}, m_cs{cs} {}
0022
0023 struct tokenizer_state {
0024 qsizetype start, end, extra;
0025 friend constexpr bool operator==(tokenizer_state lhs, tokenizer_state rhs) noexcept
0026 { return lhs.start == rhs.start && lhs.end == rhs.end && lhs.extra == rhs.extra; }
0027 friend constexpr bool operator!=(tokenizer_state lhs, tokenizer_state rhs) noexcept
0028 { return !operator==(lhs, rhs); }
0029 };
0030
0031 Qt::SplitBehavior m_sb;
0032 Qt::CaseSensitivity m_cs;
0033 };
0034
0035 template <typename Haystack, typename Needle>
0036 class QStringTokenizerBase : protected QStringTokenizerBaseBase
0037 {
0038 struct next_result {
0039 Haystack value;
0040 bool ok;
0041 tokenizer_state state;
0042 };
0043 inline next_result next(tokenizer_state state) const noexcept;
0044 inline next_result toFront() const noexcept { return next({}); }
0045 public:
0046 constexpr explicit QStringTokenizerBase(Haystack haystack, Needle needle, Qt::SplitBehavior sb, Qt::CaseSensitivity cs) noexcept
0047 : QStringTokenizerBaseBase{sb, cs}, m_haystack{haystack}, m_needle{needle} {}
0048
0049 class iterator;
0050 friend class iterator;
0051 class sentinel {
0052 friend constexpr bool operator==(sentinel, sentinel) noexcept { return true; }
0053 friend constexpr bool operator!=(sentinel, sentinel) noexcept { return false; }
0054 };
0055 class iterator {
0056 const QStringTokenizerBase *tokenizer;
0057 next_result current;
0058 friend class QStringTokenizerBase;
0059 explicit iterator(const QStringTokenizerBase &t) noexcept
0060 : tokenizer{&t}, current{t.toFront()} {}
0061 public:
0062 using difference_type = qsizetype;
0063 using value_type = Haystack;
0064 using pointer = const value_type*;
0065 using reference = const value_type&;
0066 using iterator_category = std::forward_iterator_tag;
0067
0068 iterator() noexcept = default;
0069
0070
0071 [[nodiscard]] constexpr const Haystack* operator->() const { return Q_ASSERT(current.ok), ¤t.value; }
0072 [[nodiscard]] constexpr const Haystack& operator*() const { return *operator->(); }
0073
0074 iterator& operator++() { advance(); return *this; }
0075 iterator operator++(int) { auto tmp = *this; advance(); return tmp; }
0076
0077 friend constexpr bool operator==(const iterator &lhs, sentinel) noexcept
0078 { return !lhs.current.ok; }
0079 friend constexpr bool operator!=(const iterator &lhs, sentinel) noexcept
0080 { return !operator==(lhs, sentinel{}); }
0081 friend constexpr bool operator==(sentinel, const iterator &rhs) noexcept
0082 { return !rhs.current.ok; }
0083 friend constexpr bool operator!=(sentinel, const iterator &rhs) noexcept
0084 { return !operator==(sentinel{}, rhs); }
0085 private:
0086 void advance() {
0087 Q_ASSERT(current.ok);
0088 current = tokenizer->next(current.state);
0089 }
0090 };
0091 using const_iterator = iterator;
0092
0093 using size_type = std::size_t;
0094 using difference_type = typename iterator::difference_type;
0095 using value_type = typename iterator::value_type;
0096 using pointer = typename iterator::pointer;
0097 using const_pointer = pointer;
0098 using reference = typename iterator::reference;
0099 using const_reference = reference;
0100
0101 [[nodiscard]] iterator begin() const noexcept { return iterator{*this}; }
0102 [[nodiscard]] iterator cbegin() const noexcept { return begin(); }
0103 [[nodiscard]] constexpr sentinel end() const noexcept { return {}; }
0104 [[nodiscard]] constexpr sentinel cend() const noexcept { return {}; }
0105
0106 private:
0107 Haystack m_haystack;
0108 Needle m_needle;
0109 };
0110
0111 QT_BEGIN_INCLUDE_NAMESPACE
0112 #include <QtCore/qstringview.h>
0113 QT_END_INCLUDE_NAMESPACE
0114
0115 namespace QtPrivate {
0116 namespace Tok {
0117
0118 constexpr qsizetype tokenSize(QChar) noexcept { return 1; }
0119 template <typename String>
0120 constexpr qsizetype tokenSize(const String &s) noexcept { return static_cast<qsizetype>(s.size()); }
0121
0122 template <typename String> struct ViewForImpl {};
0123 template <> struct ViewForImpl<QStringView> { using type = QStringView; };
0124 template <> struct ViewForImpl<QLatin1StringView> { using type = QLatin1StringView; };
0125 template <> struct ViewForImpl<QChar> { using type = QChar; };
0126 template <> struct ViewForImpl<QString> : ViewForImpl<QStringView> {};
0127 template <> struct ViewForImpl<QLatin1Char> : ViewForImpl<QChar> {};
0128 template <> struct ViewForImpl<char16_t> : ViewForImpl<QChar> {};
0129 template <> struct ViewForImpl<char16_t*> : ViewForImpl<QStringView> {};
0130 template <> struct ViewForImpl<const char16_t*> : ViewForImpl<QStringView> {};
0131 template <typename LHS, typename RHS>
0132 struct ViewForImpl<QStringBuilder<LHS, RHS>> : ViewForImpl<typename QStringBuilder<LHS,RHS>::ConvertTo> {};
0133 template <typename Char, typename...Args>
0134 struct ViewForImpl<std::basic_string<Char, Args...>> : ViewForImpl<Char*> {};
0135 #ifdef __cpp_lib_string_view
0136 template <typename Char, typename...Args>
0137 struct ViewForImpl<std::basic_string_view<Char, Args...>> : ViewForImpl<Char*> {};
0138 #endif
0139
0140
0141
0142
0143
0144 template <typename String>
0145 using ViewFor = typename ViewForImpl<typename std::decay<String>::type>::type;
0146
0147
0148
0149
0150
0151
0152
0153 template <typename String>
0154 struct PinForImpl { using type = ViewFor<String>; };
0155
0156
0157 template <>
0158 struct PinForImpl<QString> { using type = QString; };
0159
0160
0161 template <typename Char, typename...Args>
0162 struct PinForImpl<std::basic_string<Char, Args...>>
0163 { using type = std::basic_string<Char, Args...>; };
0164
0165
0166 template <typename LHS, typename RHS>
0167 struct PinForImpl<QStringBuilder<LHS, RHS>>
0168 : PinForImpl<typename QStringBuilder<LHS, RHS>::ConvertTo> {};
0169
0170 template <typename StringLike>
0171 using PinFor = typename PinForImpl<typename std::remove_cv<StringLike>::type>::type;
0172
0173 template <typename T> struct is_owning_string_type : std::false_type {};
0174 template <> struct is_owning_string_type<QString> : std::true_type {};
0175 template <typename...Args> struct is_owning_string_type<std::basic_string<Args...>> : std::true_type {};
0176
0177
0178 template <typename T, bool pinned = is_owning_string_type<T>::value>
0179 struct Pinning
0180 {
0181
0182 constexpr Pinning(const T&) noexcept {}
0183
0184
0185 constexpr T view(T t) const noexcept { return t; }
0186 };
0187
0188
0189 template <typename T>
0190 struct Pinning<T, true>
0191 {
0192 T m_string;
0193
0194
0195 constexpr Pinning(T &&s) noexcept : m_string{std::move(s)} {}
0196
0197 constexpr QStringView view(const T&) const noexcept { return m_string; }
0198 };
0199
0200
0201
0202
0203 template <typename T>
0204 struct NeedlePinning : Pinning<T>
0205 {
0206 using Pinning<T>::Pinning;
0207 template <typename Arg>
0208 constexpr auto needleView(Arg &&a) noexcept
0209 -> decltype(this->view(std::forward<Arg>(a)))
0210 { return this->view(std::forward<Arg>(a)); }
0211 };
0212
0213 template <typename T>
0214 struct HaystackPinning : Pinning<T>
0215 {
0216 using Pinning<T>::Pinning;
0217 template <typename Arg>
0218 constexpr auto haystackView(Arg &&a) noexcept
0219 -> decltype(this->view(std::forward<Arg>(a)))
0220 { return this->view(std::forward<Arg>(a)); }
0221 };
0222
0223
0224
0225
0226
0227
0228 template <typename Haystack, typename Needle>
0229 using TokenizerBase = QStringTokenizerBase<ViewFor<Haystack>, ViewFor<Needle>>;
0230 }
0231 }
0232
0233 template <typename Haystack, typename Needle>
0234 class QStringTokenizer
0235 : private QtPrivate::Tok::HaystackPinning<Haystack>,
0236 private QtPrivate::Tok::NeedlePinning<Needle>,
0237 public QtPrivate::Tok::TokenizerBase<Haystack, Needle>
0238 {
0239 using HPin = QtPrivate::Tok::HaystackPinning<Haystack>;
0240 using NPin = QtPrivate::Tok::NeedlePinning<Needle>;
0241 using Base = QtPrivate::Tok::TokenizerBase<Haystack, Needle>;
0242 template <typename Container, typename HPin>
0243 struct if_haystack_not_pinned_impl : std::enable_if<std::is_empty<HPin>::value, bool> {};
0244 template <typename Container>
0245 using if_haystack_not_pinned = typename if_haystack_not_pinned_impl<Container, HPin>::type;
0246 template <typename Container, typename Iterator = decltype(std::begin(std::declval<Container>()))>
0247 using if_compatible_container = typename std::enable_if<
0248 std::is_convertible<
0249 typename Base::value_type,
0250 typename std::iterator_traits<Iterator>::value_type
0251 >::value,
0252 bool
0253 >::type;
0254 public:
0255 using value_type = typename Base::value_type;
0256 using difference_type = typename Base::difference_type;
0257 using size_type = typename Base::size_type;
0258 using reference = typename Base::reference;
0259 using const_reference = typename Base::const_reference;
0260 using pointer = typename Base::pointer;
0261 using const_pointer = typename Base::const_pointer;
0262 using iterator = typename Base::iterator;
0263 using const_iterator = typename Base::const_iterator;
0264 using sentinel = typename Base::sentinel;
0265
0266 #ifdef Q_QDOC
0267 [[nodiscard]] iterator begin() const noexcept { return Base::begin(); }
0268 [[nodiscard]] iterator cbegin() const noexcept { return begin(); }
0269 [[nodiscard]] constexpr sentinel end() const noexcept { return {}; }
0270 [[nodiscard]] constexpr sentinel cend() const noexcept { return {}; }
0271 #endif
0272
0273 constexpr explicit QStringTokenizer(Haystack haystack, Needle needle,
0274 Qt::CaseSensitivity cs,
0275 Qt::SplitBehavior sb = Qt::KeepEmptyParts)
0276 noexcept(std::is_nothrow_copy_constructible<QStringTokenizer>::value)
0277
0278
0279
0280
0281 : HPin{std::forward<Haystack>(haystack)},
0282 NPin{std::forward<Needle>(needle)},
0283
0284
0285 Base{this->haystackView(haystack),
0286 this->needleView(needle), sb, cs}
0287 {}
0288 constexpr explicit QStringTokenizer(Haystack haystack, Needle needle,
0289 Qt::SplitBehavior sb = Qt::KeepEmptyParts,
0290 Qt::CaseSensitivity cs = Qt::CaseSensitive)
0291 noexcept(std::is_nothrow_copy_constructible<QStringTokenizer>::value)
0292 : HPin{std::forward<Haystack>(haystack)},
0293 NPin{std::forward<Needle>(needle)},
0294 Base{this->haystackView(haystack),
0295 this->needleView(needle), sb, cs}
0296 {}
0297
0298 #ifdef Q_QDOC
0299 template<typename LContainer> LContainer toContainer(LContainer &&c = {}) const & {}
0300 template<typename RContainer> RContainer toContainer(RContainer &&c = {}) const && {}
0301 #else
0302 template<typename Container = QList<value_type>, if_compatible_container<Container> = true>
0303 Container toContainer(Container &&c = {}) const &
0304 {
0305 for (auto e : *this)
0306 c.emplace_back(e);
0307 return std::forward<Container>(c);
0308 }
0309 template<typename Container = QList<value_type>, if_compatible_container<Container> = true,
0310 if_haystack_not_pinned<Container> = true>
0311 Container toContainer(Container &&c = {}) const &&
0312 {
0313 for (auto e : *this)
0314 c.emplace_back(e);
0315 return std::forward<Container>(c);
0316 }
0317 #endif
0318 };
0319
0320 namespace QtPrivate {
0321 namespace Tok {
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 #define Q_TOK_RESULT \
0334 QStringTokenizer< \
0335 QtPrivate::Tok::PinFor<Haystack>, \
0336 QtPrivate::Tok::PinFor<Needle> \
0337 > \
0338
0339 template <typename Haystack, typename Needle>
0340 using TokenizerResult = Q_TOK_RESULT;
0341 template <typename Haystack, typename Needle>
0342 using is_nothrow_constructible_from = std::is_nothrow_copy_constructible<TokenizerResult<Haystack, Needle>>;
0343 }
0344 }
0345
0346 #ifdef __cpp_deduction_guides
0347
0348
0349 template <typename Haystack, typename Needle>
0350 QStringTokenizer(Haystack&&, Needle&&)
0351 -> Q_TOK_RESULT;
0352 template <typename Haystack, typename Needle>
0353 QStringTokenizer(Haystack&&, Needle&&, Qt::SplitBehavior)
0354 -> Q_TOK_RESULT;
0355 template <typename Haystack, typename Needle>
0356 QStringTokenizer(Haystack&&, Needle&&, Qt::SplitBehavior, Qt::CaseSensitivity)
0357 -> Q_TOK_RESULT;
0358 template <typename Haystack, typename Needle>
0359 QStringTokenizer(Haystack&&, Needle&&, Qt::CaseSensitivity)
0360 -> Q_TOK_RESULT;
0361 template <typename Haystack, typename Needle>
0362 QStringTokenizer(Haystack&&, Needle&&, Qt::CaseSensitivity, Qt::SplitBehavior)
0363 -> Q_TOK_RESULT;
0364 #endif
0365
0366 #undef Q_TOK_RESULT
0367
0368 template <typename Haystack, typename Needle, typename...Flags>
0369 [[nodiscard]] constexpr auto
0370 qTokenize(Haystack &&h, Needle &&n, Flags...flags)
0371 noexcept(QtPrivate::Tok::is_nothrow_constructible_from<Haystack, Needle>::value)
0372 -> decltype(QtPrivate::Tok::TokenizerResult<Haystack, Needle>{std::forward<Haystack>(h),
0373 std::forward<Needle>(n), flags...})
0374 { return QtPrivate::Tok::TokenizerResult<Haystack, Needle>{std::forward<Haystack>(h),
0375 std::forward<Needle>(n),
0376 flags...}; }
0377
0378 template <typename Haystack, typename Needle>
0379 auto QStringTokenizerBase<Haystack, Needle>::next(tokenizer_state state) const noexcept -> next_result
0380 {
0381 while (true) {
0382 if (state.end < 0) {
0383
0384 return {{}, false, state};
0385 }
0386 state.end = m_haystack.indexOf(m_needle, state.start + state.extra, m_cs);
0387 Haystack result;
0388 if (state.end >= 0) {
0389
0390 result = m_haystack.sliced(state.start, state.end - state.start);
0391 const auto ns = QtPrivate::Tok::tokenSize(m_needle);
0392 state.start = state.end + ns;
0393 state.extra = (ns == 0 ? 1 : 0);
0394 } else {
0395
0396 result = m_haystack.sliced(state.start);
0397 }
0398 if ((m_sb & Qt::SkipEmptyParts) && result.isEmpty())
0399 continue;
0400 return {result, true, state};
0401 }
0402 }
0403
0404 QT_END_NAMESPACE
0405
0406 #endif