File indexing completed on 2025-01-18 09:27:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
0030 #define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
0031
0032 #include <array>
0033 #include <cstddef>
0034 #include <initializer_list>
0035 #include <iterator>
0036 #include <tuple>
0037 #include <type_traits>
0038 #include <utility>
0039 #include <vector>
0040
0041 #include "absl/base/macros.h"
0042 #include "absl/base/port.h"
0043 #include "absl/meta/type_traits.h"
0044 #include "absl/strings/string_view.h"
0045
0046 #ifdef _GLIBCXX_DEBUG
0047 #include "absl/strings/internal/stl_type_traits.h"
0048 #endif
0049
0050 namespace absl {
0051 ABSL_NAMESPACE_BEGIN
0052 namespace strings_internal {
0053
0054
0055
0056
0057
0058 class ConvertibleToStringView {
0059 public:
0060 ConvertibleToStringView(const char* s)
0061 : value_(s) {}
0062 ConvertibleToStringView(char* s) : value_(s) {}
0063 ConvertibleToStringView(absl::string_view s)
0064 : value_(s) {}
0065 ConvertibleToStringView(const std::string& s)
0066 : value_(s) {}
0067
0068
0069 ConvertibleToStringView(std::string&& s) = delete;
0070 ConvertibleToStringView(const std::string&& s) = delete;
0071
0072 absl::string_view value() const { return value_; }
0073
0074 private:
0075 absl::string_view value_;
0076 };
0077
0078
0079
0080
0081
0082
0083
0084 template <typename Splitter>
0085 class SplitIterator {
0086 public:
0087 using iterator_category = std::input_iterator_tag;
0088 using value_type = absl::string_view;
0089 using difference_type = ptrdiff_t;
0090 using pointer = const value_type*;
0091 using reference = const value_type&;
0092
0093 enum State { kInitState, kLastState, kEndState };
0094 SplitIterator(State state, const Splitter* splitter)
0095 : pos_(0),
0096 state_(state),
0097 splitter_(splitter),
0098 delimiter_(splitter->delimiter()),
0099 predicate_(splitter->predicate()) {
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 if (splitter_->text().data() == nullptr) {
0110 state_ = kEndState;
0111 pos_ = splitter_->text().size();
0112 return;
0113 }
0114
0115 if (state_ == kEndState) {
0116 pos_ = splitter_->text().size();
0117 } else {
0118 ++(*this);
0119 }
0120 }
0121
0122 bool at_end() const { return state_ == kEndState; }
0123
0124 reference operator*() const { return curr_; }
0125 pointer operator->() const { return &curr_; }
0126
0127 SplitIterator& operator++() {
0128 do {
0129 if (state_ == kLastState) {
0130 state_ = kEndState;
0131 return *this;
0132 }
0133 const absl::string_view text = splitter_->text();
0134 const absl::string_view d = delimiter_.Find(text, pos_);
0135 if (d.data() == text.data() + text.size()) state_ = kLastState;
0136 curr_ = text.substr(pos_,
0137 static_cast<size_t>(d.data() - (text.data() + pos_)));
0138 pos_ += curr_.size() + d.size();
0139 } while (!predicate_(curr_));
0140 return *this;
0141 }
0142
0143 SplitIterator operator++(int) {
0144 SplitIterator old(*this);
0145 ++(*this);
0146 return old;
0147 }
0148
0149 friend bool operator==(const SplitIterator& a, const SplitIterator& b) {
0150 return a.state_ == b.state_ && a.pos_ == b.pos_;
0151 }
0152
0153 friend bool operator!=(const SplitIterator& a, const SplitIterator& b) {
0154 return !(a == b);
0155 }
0156
0157 private:
0158 size_t pos_;
0159 State state_;
0160 absl::string_view curr_;
0161 const Splitter* splitter_;
0162 typename Splitter::DelimiterType delimiter_;
0163 typename Splitter::PredicateType predicate_;
0164 };
0165
0166
0167 template <typename T, typename = void>
0168 struct HasMappedType : std::false_type {};
0169 template <typename T>
0170 struct HasMappedType<T, absl::void_t<typename T::mapped_type>>
0171 : std::true_type {};
0172
0173
0174 template <typename T, typename = void>
0175 struct HasValueType : std::false_type {};
0176 template <typename T>
0177 struct HasValueType<T, absl::void_t<typename T::value_type>> : std::true_type {
0178 };
0179
0180
0181 template <typename T, typename = void>
0182 struct HasConstIterator : std::false_type {};
0183 template <typename T>
0184 struct HasConstIterator<T, absl::void_t<typename T::const_iterator>>
0185 : std::true_type {};
0186
0187
0188 template <typename T, typename = void>
0189 struct HasEmplace : std::false_type {};
0190 template <typename T>
0191 struct HasEmplace<T, absl::void_t<decltype(std::declval<T>().emplace())>>
0192 : std::true_type {};
0193
0194
0195
0196 std::false_type IsInitializerListDispatch(...);
0197 template <typename T>
0198 std::true_type IsInitializerListDispatch(std::initializer_list<T>*);
0199 template <typename T>
0200 struct IsInitializerList
0201 : decltype(IsInitializerListDispatch(static_cast<T*>(nullptr))) {};
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 template <typename C, bool has_value_type, bool has_mapped_type>
0214 struct SplitterIsConvertibleToImpl : std::false_type {};
0215
0216 template <typename C>
0217 struct SplitterIsConvertibleToImpl<C, true, false>
0218 : std::is_constructible<typename C::value_type, absl::string_view> {};
0219
0220 template <typename C>
0221 struct SplitterIsConvertibleToImpl<C, true, true>
0222 : absl::conjunction<
0223 std::is_constructible<typename C::key_type, absl::string_view>,
0224 std::is_constructible<typename C::mapped_type, absl::string_view>> {};
0225
0226 template <typename C>
0227 struct SplitterIsConvertibleTo
0228 : SplitterIsConvertibleToImpl<
0229 C,
0230 #ifdef _GLIBCXX_DEBUG
0231 !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value &&
0232 #endif
0233 !IsInitializerList<
0234 typename std::remove_reference<C>::type>::value &&
0235 HasValueType<C>::value && HasConstIterator<C>::value,
0236 HasMappedType<C>::value> {
0237 };
0238
0239 template <typename StringType, typename Container, typename = void>
0240 struct ShouldUseLifetimeBound : std::false_type {};
0241
0242 template <typename StringType, typename Container>
0243 struct ShouldUseLifetimeBound<
0244 StringType, Container,
0245 std::enable_if_t<
0246 std::is_same<StringType, std::string>::value &&
0247 std::is_same<typename Container::value_type, absl::string_view>::value>>
0248 : std::true_type {};
0249
0250 template <typename StringType, typename First, typename Second>
0251 using ShouldUseLifetimeBoundForPair = std::integral_constant<
0252 bool, std::is_same<StringType, std::string>::value &&
0253 (std::is_same<First, absl::string_view>::value ||
0254 std::is_same<Second, absl::string_view>::value)>;
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 template <typename Delimiter, typename Predicate, typename StringType>
0279 class Splitter {
0280 public:
0281 using DelimiterType = Delimiter;
0282 using PredicateType = Predicate;
0283 using const_iterator = strings_internal::SplitIterator<Splitter>;
0284 using value_type = typename std::iterator_traits<const_iterator>::value_type;
0285
0286 Splitter(StringType input_text, Delimiter d, Predicate p)
0287 : text_(std::move(input_text)),
0288 delimiter_(std::move(d)),
0289 predicate_(std::move(p)) {}
0290
0291 absl::string_view text() const { return text_; }
0292 const Delimiter& delimiter() const { return delimiter_; }
0293 const Predicate& predicate() const { return predicate_; }
0294
0295
0296
0297
0298 const_iterator begin() const { return {const_iterator::kInitState, this}; }
0299 const_iterator end() const { return {const_iterator::kEndState, this}; }
0300
0301
0302
0303 template <
0304 typename Container,
0305 std::enable_if_t<ShouldUseLifetimeBound<StringType, Container>::value &&
0306 SplitterIsConvertibleTo<Container>::value,
0307 std::nullptr_t> = nullptr>
0308
0309 operator Container() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0310 return ConvertToContainer<Container, typename Container::value_type,
0311 HasMappedType<Container>::value>()(*this);
0312 }
0313
0314 template <
0315 typename Container,
0316 std::enable_if_t<!ShouldUseLifetimeBound<StringType, Container>::value &&
0317 SplitterIsConvertibleTo<Container>::value,
0318 std::nullptr_t> = nullptr>
0319
0320 operator Container() const {
0321 return ConvertToContainer<Container, typename Container::value_type,
0322 HasMappedType<Container>::value>()(*this);
0323 }
0324
0325
0326
0327
0328
0329 template <typename First, typename Second,
0330 std::enable_if_t<
0331 ShouldUseLifetimeBoundForPair<StringType, First, Second>::value,
0332 std::nullptr_t> = nullptr>
0333
0334 operator std::pair<First, Second>() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0335 return ConvertToPair<First, Second>();
0336 }
0337
0338 template <typename First, typename Second,
0339 std::enable_if_t<!ShouldUseLifetimeBoundForPair<StringType, First,
0340 Second>::value,
0341 std::nullptr_t> = nullptr>
0342
0343 operator std::pair<First, Second>() const {
0344 return ConvertToPair<First, Second>();
0345 }
0346
0347 private:
0348 template <typename First, typename Second>
0349 std::pair<First, Second> ConvertToPair() const {
0350 absl::string_view first, second;
0351 auto it = begin();
0352 if (it != end()) {
0353 first = *it;
0354 if (++it != end()) {
0355 second = *it;
0356 }
0357 }
0358 return {First(first), Second(second)};
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368 template <typename Container, typename ValueType, bool is_map = false>
0369 struct ConvertToContainer {
0370 Container operator()(const Splitter& splitter) const {
0371 Container c;
0372 auto it = std::inserter(c, c.end());
0373 for (const auto& sp : splitter) {
0374 *it++ = ValueType(sp);
0375 }
0376 return c;
0377 }
0378 };
0379
0380
0381
0382
0383
0384
0385 template <typename A>
0386 struct ConvertToContainer<std::vector<absl::string_view, A>,
0387 absl::string_view, false> {
0388 std::vector<absl::string_view, A> operator()(
0389 const Splitter& splitter) const {
0390 struct raw_view {
0391 const char* data;
0392 size_t size;
0393 operator absl::string_view() const {
0394 return {data, size};
0395 }
0396 };
0397 std::vector<absl::string_view, A> v;
0398 std::array<raw_view, 16> ar;
0399 for (auto it = splitter.begin(); !it.at_end();) {
0400 size_t index = 0;
0401 do {
0402 ar[index].data = it->data();
0403 ar[index].size = it->size();
0404 ++it;
0405 } while (++index != ar.size() && !it.at_end());
0406
0407
0408 v.insert(v.end(), ar.begin(),
0409 ar.begin() + static_cast<ptrdiff_t>(index));
0410 }
0411 return v;
0412 }
0413 };
0414
0415
0416
0417
0418
0419
0420
0421 template <typename A>
0422 struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {
0423 std::vector<std::string, A> operator()(const Splitter& splitter) const {
0424 const std::vector<absl::string_view> v = splitter;
0425 return std::vector<std::string, A>(v.begin(), v.end());
0426 }
0427 };
0428
0429
0430
0431
0432
0433
0434
0435 template <typename Container, typename First, typename Second>
0436 struct ConvertToContainer<Container, std::pair<const First, Second>, true> {
0437 using iterator = typename Container::iterator;
0438
0439 Container operator()(const Splitter& splitter) const {
0440 Container m;
0441 iterator it;
0442 bool insert = true;
0443 for (const absl::string_view sv : splitter) {
0444 if (insert) {
0445 it = InsertOrEmplace(&m, sv);
0446 } else {
0447 it->second = Second(sv);
0448 }
0449 insert = !insert;
0450 }
0451 return m;
0452 }
0453
0454
0455
0456 template <typename M>
0457 static absl::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(
0458 M* m, absl::string_view key) {
0459
0460
0461 return ToIter(m->emplace(std::piecewise_construct, std::make_tuple(key),
0462 std::tuple<>()));
0463 }
0464 template <typename M>
0465 static absl::enable_if_t<!HasEmplace<M>::value, iterator> InsertOrEmplace(
0466 M* m, absl::string_view key) {
0467 return ToIter(m->insert(std::make_pair(First(key), Second(""))));
0468 }
0469
0470 static iterator ToIter(std::pair<iterator, bool> pair) {
0471 return pair.first;
0472 }
0473 static iterator ToIter(iterator iter) { return iter; }
0474 };
0475
0476 StringType text_;
0477 Delimiter delimiter_;
0478 Predicate predicate_;
0479 };
0480
0481 }
0482 ABSL_NAMESPACE_END
0483 }
0484
0485 #endif