Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:26

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 
0016 // This file declares INTERNAL parts of the Split API that are inline/templated
0017 // or otherwise need to be available at compile time. The main abstractions
0018 // defined in here are
0019 //
0020 //   - ConvertibleToStringView
0021 //   - SplitIterator<>
0022 //   - Splitter<>
0023 //
0024 // DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including
0025 // absl/strings/str_split.h.
0026 //
0027 // IWYU pragma: private, include "absl/strings/str_split.h"
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  // _GLIBCXX_DEBUG
0049 
0050 namespace absl {
0051 ABSL_NAMESPACE_BEGIN
0052 namespace strings_internal {
0053 
0054 // This class is implicitly constructible from everything that absl::string_view
0055 // is implicitly constructible from, except for rvalue strings.  This means it
0056 // can be used as a function parameter in places where passing a temporary
0057 // string might cause memory lifetime issues.
0058 class ConvertibleToStringView {
0059  public:
0060   ConvertibleToStringView(const char* s)  // NOLINT(runtime/explicit)
0061       : value_(s) {}
0062   ConvertibleToStringView(char* s) : value_(s) {}  // NOLINT(runtime/explicit)
0063   ConvertibleToStringView(absl::string_view s)     // NOLINT(runtime/explicit)
0064       : value_(s) {}
0065   ConvertibleToStringView(const std::string& s)  // NOLINT(runtime/explicit)
0066       : value_(s) {}
0067 
0068   // Disable conversion from rvalue strings.
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 // An iterator that enumerates the parts of a string from a Splitter. The text
0079 // to be split, the Delimiter, and the Predicate are all taken from the given
0080 // Splitter object. Iterators may only be compared if they refer to the same
0081 // Splitter instance.
0082 //
0083 // This class is NOT part of the public splitting API.
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     // Hack to maintain backward compatibility. This one block makes it so an
0101     // empty absl::string_view whose .data() happens to be nullptr behaves
0102     // *differently* from an otherwise empty absl::string_view whose .data() is
0103     // not nullptr. This is an undesirable difference in general, but this
0104     // behavior is maintained to avoid breaking existing code that happens to
0105     // depend on this old behavior/bug. Perhaps it will be fixed one day. The
0106     // difference in behavior is as follows:
0107     //   Split(absl::string_view(""), '-');  // {""}
0108     //   Split(absl::string_view(), '-');    // {}
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 // HasMappedType<T>::value is true iff there exists a type T::mapped_type.
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 // HasValueType<T>::value is true iff there exists a type T::value_type.
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 // HasConstIterator<T>::value is true iff there exists a type T::const_iterator.
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 // HasEmplace<T>::value is true iff there exists a method T::emplace().
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 // IsInitializerList<T>::value is true iff T is an std::initializer_list. More
0195 // details below in Splitter<> where this is used.
0196 std::false_type IsInitializerListDispatch(...);  // default: No
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 // A SplitterIsConvertibleTo<C>::type alias exists iff the specified condition
0204 // is true for type 'C'.
0205 //
0206 // Restricts conversion to container-like types (by testing for the presence of
0207 // a const_iterator member type) and also to disable conversion to an
0208 // std::initializer_list (which also has a const_iterator). Otherwise, code
0209 // compiled in C++11 will get an error due to ambiguous conversion paths (in
0210 // C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T>
0211 // or an std::initializer_list<T>).
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  // _GLIBCXX_DEBUG
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 // This class implements the range that is returned by absl::StrSplit(). This
0258 // class has templated conversion operators that allow it to be implicitly
0259 // converted to a variety of types that the caller may have specified on the
0260 // left-hand side of an assignment.
0261 //
0262 // The main interface for interacting with this class is through its implicit
0263 // conversion operators. However, this class may also be used like a container
0264 // in that it has .begin() and .end() member functions. It may also be used
0265 // within a range-for loop.
0266 //
0267 // Output containers can be collections of any type that is constructible from
0268 // an absl::string_view.
0269 //
0270 // An Predicate functor may be supplied. This predicate will be used to filter
0271 // the split strings: only strings for which the predicate returns true will be
0272 // kept. A Predicate object is any unary functor that takes an absl::string_view
0273 // and returns bool.
0274 //
0275 // The StringType parameter can be either string_view or string, depending on
0276 // whether the Splitter refers to a string stored elsewhere, or if the string
0277 // resides inside the Splitter itself.
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   // Range functions that iterate the split substrings as absl::string_view
0296   // objects. These methods enable a Splitter to be used in a range-based for
0297   // loop.
0298   const_iterator begin() const { return {const_iterator::kInitState, this}; }
0299   const_iterator end() const { return {const_iterator::kEndState, this}; }
0300 
0301   // An implicit conversion operator that is restricted to only those containers
0302   // that the splitter is convertible to.
0303   template <
0304       typename Container,
0305       std::enable_if_t<ShouldUseLifetimeBound<StringType, Container>::value &&
0306                            SplitterIsConvertibleTo<Container>::value,
0307                        std::nullptr_t> = nullptr>
0308   // NOLINTNEXTLINE(google-explicit-constructor)
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   // NOLINTNEXTLINE(google-explicit-constructor)
0320   operator Container() const {
0321     return ConvertToContainer<Container, typename Container::value_type,
0322                               HasMappedType<Container>::value>()(*this);
0323   }
0324 
0325   // Returns a pair with its .first and .second members set to the first two
0326   // strings returned by the begin() iterator. Either/both of .first and .second
0327   // will be constructed with empty strings if the iterator doesn't have a
0328   // corresponding value.
0329   template <typename First, typename Second,
0330             std::enable_if_t<
0331                 ShouldUseLifetimeBoundForPair<StringType, First, Second>::value,
0332                 std::nullptr_t> = nullptr>
0333   // NOLINTNEXTLINE(google-explicit-constructor)
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   // NOLINTNEXTLINE(google-explicit-constructor)
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   // ConvertToContainer is a functor converting a Splitter to the requested
0362   // Container of ValueType. It is specialized below to optimize splitting to
0363   // certain combinations of Container and ValueType.
0364   //
0365   // This base template handles the generic case of storing the split results in
0366   // the requested non-map-like container and converting the split substrings to
0367   // the requested type.
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   // Partial specialization for a std::vector<absl::string_view>.
0381   //
0382   // Optimized for the common case of splitting to a
0383   // std::vector<absl::string_view>. In this case we first split the results to
0384   // a small array of absl::string_view on the stack, to reduce reallocations.
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 {  // NOLINT(runtime/explicit)
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         // We static_cast index to a signed type to work around overzealous
0407         // compiler warnings about signedness.
0408         v.insert(v.end(), ar.begin(),
0409                  ar.begin() + static_cast<ptrdiff_t>(index));
0410       }
0411       return v;
0412     }
0413   };
0414 
0415   // Partial specialization for a std::vector<std::string>.
0416   //
0417   // Optimized for the common case of splitting to a std::vector<std::string>.
0418   // In this case we first split the results to a std::vector<absl::string_view>
0419   // so the returned std::vector<std::string> can have space reserved to avoid
0420   // std::string moves.
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   // Partial specialization for containers of pairs (e.g., maps).
0430   //
0431   // The algorithm is to insert a new pair into the map for each even-numbered
0432   // item, with the even-numbered item as the key with a default-constructed
0433   // value. Each odd-numbered item will then be assigned to the last pair's
0434   // value.
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     // Inserts the key and an empty value into the map, returning an iterator to
0455     // the inserted item. We use emplace() if available, otherwise insert().
0456     template <typename M>
0457     static absl::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(
0458         M* m, absl::string_view key) {
0459       // Use piecewise_construct to support old versions of gcc in which pair
0460       // constructor can't otherwise construct string from string_view.
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 }  // namespace strings_internal
0482 ABSL_NAMESPACE_END
0483 }  // namespace absl
0484 
0485 #endif  // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_