/Users/deen/code/yugabyte-db/src/yb/gutil/strings/split_internal.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2012 Google Inc. All Rights Reserved. |
2 | | // |
3 | | // The following only applies to changes made to this file as part of YugaByte development. |
4 | | // |
5 | | // Portions Copyright (c) YugaByte, Inc. |
6 | | // |
7 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
8 | | // in compliance with the License. You may obtain a copy of the License at |
9 | | // |
10 | | // http://www.apache.org/licenses/LICENSE-2.0 |
11 | | // |
12 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
13 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
14 | | // or implied. See the License for the specific language governing permissions and limitations |
15 | | // under the License. |
16 | | // |
17 | | // This file declares INTERNAL parts of the Split API that are inline/templated |
18 | | // or otherwise need to be available at compile time. The main two abstractions |
19 | | // defined in here are |
20 | | // |
21 | | // - SplitIterator<> |
22 | | // - Splitter<> |
23 | | // |
24 | | // Everything else is plumbing for those two. |
25 | | // |
26 | | // DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including |
27 | | // strings/split.h. |
28 | | // |
29 | | // IWYU pragma: private, include "strings/split.h" |
30 | | |
31 | | #ifndef YB_GUTIL_STRINGS_SPLIT_INTERNAL_H |
32 | | #define YB_GUTIL_STRINGS_SPLIT_INTERNAL_H |
33 | | |
34 | | #include <iterator> |
35 | | using std::back_insert_iterator; |
36 | | using std::iterator_traits; |
37 | | #include <map> |
38 | | using std::map; |
39 | | using std::multimap; |
40 | | #include <vector> |
41 | | using std::vector; |
42 | | |
43 | | #include "yb/gutil/port.h" // for LANG_CXX11 |
44 | | #include "yb/gutil/strings/stringpiece.h" |
45 | | #include "yb/gutil/type_traits.h" |
46 | | |
47 | | #ifdef LANG_CXX11 |
48 | | // This must be included after "base/port.h", which defines LANG_CXX11. |
49 | | #include <initializer_list> |
50 | | #endif // LANG_CXX11 |
51 | | |
52 | | namespace strings { |
53 | | |
54 | | namespace internal { |
55 | | |
56 | | // The default Predicate object, which doesn't filter out anything. |
57 | | struct NoFilter { |
58 | 801k | bool operator()(GStringPiece /* ignored */) { |
59 | 801k | return true; |
60 | 801k | } |
61 | | }; |
62 | | |
63 | | // This class splits a string using the given delimiter, returning the split |
64 | | // substrings via an iterator interface. An optional Predicate functor may be |
65 | | // supplied, which will be used to filter the split strings: strings for which |
66 | | // the predicate returns false will be skipped. A Predicate object is any |
67 | | // functor that takes a GStringPiece and returns bool. By default, the NoFilter |
68 | | // Predicate is used, which does not filter out anything. |
69 | | // |
70 | | // This class is NOT part of the public splitting API. |
71 | | // |
72 | | // Usage: |
73 | | // |
74 | | // using strings::delimiter::Literal; |
75 | | // Literal d(","); |
76 | | // for (SplitIterator<Literal> it("a,b,c", d), end(d); it != end; ++it) { |
77 | | // GStringPiece substring = *it; |
78 | | // DoWork(substring); |
79 | | // } |
80 | | // |
81 | | // The explicit single-argument constructor is used to create an "end" iterator. |
82 | | // The two-argument constructor is used to split the given text using the given |
83 | | // delimiter. |
84 | | template <typename Delimiter, typename Predicate = NoFilter> |
85 | | class SplitIterator |
86 | | : public std::iterator<std::input_iterator_tag, GStringPiece> { |
87 | | public: |
88 | | // Two constructors for "end" iterators. |
89 | | explicit SplitIterator(Delimiter d) |
90 | 222k | : delimiter_(std::move(d)), predicate_(), is_end_(true) {} strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::SplitIterator(strings::delimiter::Literal) Line | Count | Source | 90 | 222k | : delimiter_(std::move(d)), predicate_(), is_end_(true) {} |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::SplitIterator(strings::delimiter::AnyOf) Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::SplitIterator(strings::delimiter::LimitImpl<strings::delimiter::AnyOf>) |
91 | | SplitIterator(Delimiter d, Predicate p) |
92 | 332k | : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {} strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::SplitIterator(strings::delimiter::Literal, strings::SkipEmpty) Line | Count | Source | 92 | 332k | : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {} |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::SplitIterator(strings::delimiter::AnyOf, strings::SkipEmpty) strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::SplitIterator(strings::delimiter::Literal, strings::AllowEmpty) Line | Count | Source | 92 | 101 | : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {} |
|
93 | | // Two constructors taking the text to iterator. |
94 | | SplitIterator(GStringPiece text, Delimiter d) |
95 | | : text_(std::move(text)), |
96 | | delimiter_(std::move(d)), |
97 | | predicate_(), |
98 | 222k | is_end_(false) { |
99 | 222k | ++(*this); |
100 | 222k | } strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::SplitIterator(GStringPiece, strings::delimiter::Literal) Line | Count | Source | 98 | 222k | is_end_(false) { | 99 | 222k | ++(*this); | 100 | 222k | } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::SplitIterator(GStringPiece, strings::delimiter::AnyOf) Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::SplitIterator(GStringPiece, strings::delimiter::LimitImpl<strings::delimiter::AnyOf>) |
101 | | SplitIterator(GStringPiece text, Delimiter d, Predicate p) |
102 | | : text_(std::move(text)), |
103 | | delimiter_(std::move(d)), |
104 | | predicate_(std::move(p)), |
105 | 332k | is_end_(false) { |
106 | 332k | ++(*this); |
107 | 332k | } strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::SplitIterator(GStringPiece, strings::delimiter::Literal, strings::SkipEmpty) Line | Count | Source | 105 | 332k | is_end_(false) { | 106 | 332k | ++(*this); | 107 | 332k | } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::SplitIterator(GStringPiece, strings::delimiter::AnyOf, strings::SkipEmpty) strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::SplitIterator(GStringPiece, strings::delimiter::Literal, strings::AllowEmpty) Line | Count | Source | 105 | 101 | is_end_(false) { | 106 | 101 | ++(*this); | 107 | 101 | } |
|
108 | | |
109 | 1.20M | GStringPiece operator*() { return curr_piece_; } strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::operator*() Line | Count | Source | 109 | 399k | GStringPiece operator*() { return curr_piece_; } |
strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::operator*() Line | Count | Source | 109 | 801k | GStringPiece operator*() { return curr_piece_; } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator*() Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator*() Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::operator*() strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::operator*() Line | Count | Source | 109 | 212 | GStringPiece operator*() { return curr_piece_; } |
|
110 | 0 | GStringPiece* operator->() { return &curr_piece_; } |
111 | | |
112 | 1.75M | SplitIterator& operator++() { |
113 | 1.76M | do { |
114 | 1.76M | if (text_.end() == curr_piece_.end()) { |
115 | | // Already consumed all of text_, so we're done. |
116 | 554k | is_end_ = true; |
117 | 554k | return *this; |
118 | 554k | } |
119 | 1.21M | GStringPiece found_delimiter = delimiter_.Find(text_); |
120 | 1.21M | assert(found_delimiter.data() != NULL); |
121 | 0 | assert(text_.begin() <= found_delimiter.begin()); |
122 | 0 | assert(found_delimiter.end() <= text_.end()); |
123 | | // found_delimiter is allowed to be empty. |
124 | | // Sets curr_piece_ to all text up to but excluding the delimiter itself. |
125 | | // Sets text_ to remaining data after the delimiter. |
126 | 0 | curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin()); |
127 | 1.21M | text_.remove_prefix(found_delimiter.end() - text_.begin()); |
128 | 1.21M | } while (!predicate_(curr_piece_)); |
129 | 1.20M | return *this; |
130 | 1.75M | } strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::operator++() Line | Count | Source | 112 | 731k | SplitIterator& operator++() { | 113 | 744k | do { | 114 | 744k | if (text_.end() == curr_piece_.end()) { | 115 | | // Already consumed all of text_, so we're done. | 116 | 332k | is_end_ = true; | 117 | 332k | return *this; | 118 | 332k | } | 119 | 412k | GStringPiece found_delimiter = delimiter_.Find(text_); | 120 | 412k | assert(found_delimiter.data() != NULL); | 121 | 0 | assert(text_.begin() <= found_delimiter.begin()); | 122 | 0 | assert(found_delimiter.end() <= text_.end()); | 123 | | // found_delimiter is allowed to be empty. | 124 | | // Sets curr_piece_ to all text up to but excluding the delimiter itself. | 125 | | // Sets text_ to remaining data after the delimiter. | 126 | 0 | curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin()); | 127 | 412k | text_.remove_prefix(found_delimiter.end() - text_.begin()); | 128 | 412k | } while (!predicate_(curr_piece_)); | 129 | 399k | return *this; | 130 | 731k | } |
strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::operator++() Line | Count | Source | 112 | 1.02M | SplitIterator& operator++() { | 113 | 1.02M | do { | 114 | 1.02M | if (text_.end() == curr_piece_.end()) { | 115 | | // Already consumed all of text_, so we're done. | 116 | 222k | is_end_ = true; | 117 | 222k | return *this; | 118 | 222k | } | 119 | 801k | GStringPiece found_delimiter = delimiter_.Find(text_); | 120 | 801k | assert(found_delimiter.data() != NULL); | 121 | 0 | assert(text_.begin() <= found_delimiter.begin()); | 122 | 0 | assert(found_delimiter.end() <= text_.end()); | 123 | | // found_delimiter is allowed to be empty. | 124 | | // Sets curr_piece_ to all text up to but excluding the delimiter itself. | 125 | | // Sets text_ to remaining data after the delimiter. | 126 | 0 | curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin()); | 127 | 801k | text_.remove_prefix(found_delimiter.end() - text_.begin()); | 128 | 801k | } while (!predicate_(curr_piece_)); | 129 | 801k | return *this; | 130 | 1.02M | } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator++() Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator++() Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::operator++() strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::operator++() Line | Count | Source | 112 | 313 | SplitIterator& operator++() { | 113 | 313 | do { | 114 | 313 | if (text_.end() == curr_piece_.end()) { | 115 | | // Already consumed all of text_, so we're done. | 116 | 101 | is_end_ = true; | 117 | 101 | return *this; | 118 | 101 | } | 119 | 212 | GStringPiece found_delimiter = delimiter_.Find(text_); | 120 | 212 | assert(found_delimiter.data() != NULL); | 121 | 0 | assert(text_.begin() <= found_delimiter.begin()); | 122 | 0 | assert(found_delimiter.end() <= text_.end()); | 123 | | // found_delimiter is allowed to be empty. | 124 | | // Sets curr_piece_ to all text up to but excluding the delimiter itself. | 125 | | // Sets text_ to remaining data after the delimiter. | 126 | 0 | curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin()); | 127 | 212 | text_.remove_prefix(found_delimiter.end() - text_.begin()); | 128 | 212 | } while (!predicate_(curr_piece_)); | 129 | 212 | return *this; | 130 | 313 | } |
|
131 | | |
132 | | SplitIterator operator++(int /* postincrement */) { |
133 | | SplitIterator old(*this); |
134 | | ++(*this); |
135 | | return old; |
136 | | } |
137 | | |
138 | 1.75M | bool operator==(const SplitIterator& other) const { |
139 | | // Two "end" iterators are always equal. If the two iterators being compared |
140 | | // aren't both end iterators, then we fallback to comparing their fields. |
141 | | // Importantly, the text being split must be equal and the current piece |
142 | | // within the text being split must also be equal. The delimiter_ and |
143 | | // predicate_ fields need not be checked here because they're template |
144 | | // parameters that are already part of the SplitIterator's type. |
145 | 1.75M | return (is_end_ && other.is_end_554k ) || |
146 | 1.75M | (1.20M is_end_ == other.is_end_1.20M && |
147 | 1.20M | text_ == other.text_0 && |
148 | 1.20M | text_.data() == other.text_.data()0 && |
149 | 1.20M | curr_piece_ == other.curr_piece_0 && |
150 | 1.20M | curr_piece_.data() == other.curr_piece_.data()0 ); |
151 | 1.75M | } strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::operator==(strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty> const&) const Line | Count | Source | 138 | 731k | bool operator==(const SplitIterator& other) const { | 139 | | // Two "end" iterators are always equal. If the two iterators being compared | 140 | | // aren't both end iterators, then we fallback to comparing their fields. | 141 | | // Importantly, the text being split must be equal and the current piece | 142 | | // within the text being split must also be equal. The delimiter_ and | 143 | | // predicate_ fields need not be checked here because they're template | 144 | | // parameters that are already part of the SplitIterator's type. | 145 | 731k | return (is_end_ && other.is_end_332k ) || | 146 | 731k | (399k is_end_ == other.is_end_399k && | 147 | 399k | text_ == other.text_0 && | 148 | 399k | text_.data() == other.text_.data()0 && | 149 | 399k | curr_piece_ == other.curr_piece_0 && | 150 | 399k | curr_piece_.data() == other.curr_piece_.data()0 ); | 151 | 731k | } |
strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::operator==(strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter> const&) const Line | Count | Source | 138 | 1.02M | bool operator==(const SplitIterator& other) const { | 139 | | // Two "end" iterators are always equal. If the two iterators being compared | 140 | | // aren't both end iterators, then we fallback to comparing their fields. | 141 | | // Importantly, the text being split must be equal and the current piece | 142 | | // within the text being split must also be equal. The delimiter_ and | 143 | | // predicate_ fields need not be checked here because they're template | 144 | | // parameters that are already part of the SplitIterator's type. | 145 | 1.02M | return (is_end_ && other.is_end_222k ) || | 146 | 1.02M | (801k is_end_ == other.is_end_801k && | 147 | 801k | text_ == other.text_0 && | 148 | 801k | text_.data() == other.text_.data()0 && | 149 | 801k | curr_piece_ == other.curr_piece_0 && | 150 | 801k | curr_piece_.data() == other.curr_piece_.data()0 ); | 151 | 1.02M | } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator==(strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter> const&) const Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator==(strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter> const&) const Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::operator==(strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty> const&) const strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::operator==(strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty> const&) const Line | Count | Source | 138 | 313 | bool operator==(const SplitIterator& other) const { | 139 | | // Two "end" iterators are always equal. If the two iterators being compared | 140 | | // aren't both end iterators, then we fallback to comparing their fields. | 141 | | // Importantly, the text being split must be equal and the current piece | 142 | | // within the text being split must also be equal. The delimiter_ and | 143 | | // predicate_ fields need not be checked here because they're template | 144 | | // parameters that are already part of the SplitIterator's type. | 145 | 313 | return (is_end_ && other.is_end_101 ) || | 146 | 313 | (212 is_end_ == other.is_end_212 && | 147 | 212 | text_ == other.text_0 && | 148 | 212 | text_.data() == other.text_.data()0 && | 149 | 212 | curr_piece_ == other.curr_piece_0 && | 150 | 212 | curr_piece_.data() == other.curr_piece_.data()0 ); | 151 | 313 | } |
|
152 | | |
153 | 1.75M | bool operator!=(const SplitIterator& other) const { |
154 | 1.75M | return !(*this == other); |
155 | 1.75M | } strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty>::operator!=(strings::internal::SplitIterator<strings::delimiter::Literal, strings::SkipEmpty> const&) const Line | Count | Source | 153 | 731k | bool operator!=(const SplitIterator& other) const { | 154 | 731k | return !(*this == other); | 155 | 731k | } |
strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter>::operator!=(strings::internal::SplitIterator<strings::delimiter::Literal, strings::internal::NoFilter> const&) const Line | Count | Source | 153 | 1.02M | bool operator!=(const SplitIterator& other) const { | 154 | 1.02M | return !(*this == other); | 155 | 1.02M | } |
Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator!=(strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::internal::NoFilter> const&) const Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator!=(strings::internal::SplitIterator<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter> const&) const Unexecuted instantiation: strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty>::operator!=(strings::internal::SplitIterator<strings::delimiter::AnyOf, strings::SkipEmpty> const&) const strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty>::operator!=(strings::internal::SplitIterator<strings::delimiter::Literal, strings::AllowEmpty> const&) const Line | Count | Source | 153 | 313 | bool operator!=(const SplitIterator& other) const { | 154 | 313 | return !(*this == other); | 155 | 313 | } |
|
156 | | |
157 | | private: |
158 | | // The text being split. Modified as delimited pieces are consumed. |
159 | | GStringPiece text_; |
160 | | Delimiter delimiter_; |
161 | | Predicate predicate_; |
162 | | bool is_end_; |
163 | | // Holds the currently split piece of text. Will always refer to string data |
164 | | // within text_. This value is returned when the iterator is dereferenced. |
165 | | GStringPiece curr_piece_; |
166 | | }; |
167 | | |
168 | | // Declares a functor that can convert a GStringPiece to another type. This works |
169 | | // for any type that has a constructor (explicit or not) taking a single |
170 | | // GStringPiece argument. A specialization exists for converting to string |
171 | | // because the underlying data needs to be copied. In theory, these |
172 | | // specializations could be extended to work with other types (e.g., int32), but |
173 | | // then a solution for error reporting would need to be devised. |
174 | | template <typename To> |
175 | | struct GStringPieceTo { |
176 | 1.90k | To operator()(GStringPiece from) const { |
177 | 1.90k | return To(from); |
178 | 1.90k | } |
179 | | }; |
180 | | |
181 | | // Specialization for converting to string. |
182 | | template <> |
183 | | struct GStringPieceTo<string> { |
184 | 1.19M | string operator()(GStringPiece from) const { |
185 | 1.19M | return from.ToString(); |
186 | 1.19M | } |
187 | | }; |
188 | | |
189 | | // Specialization for converting to *const* string. |
190 | | template <> |
191 | | struct GStringPieceTo<const string> { |
192 | 0 | string operator()(GStringPiece from) const { |
193 | 0 | return from.ToString(); |
194 | 0 | } |
195 | | }; |
196 | | |
197 | | #ifdef LANG_CXX11 |
198 | | // IsNotInitializerList<T>::type exists iff T is not an initializer_list. More |
199 | | // details below in Splitter<> where this is used. |
200 | | template <typename T> |
201 | | struct IsNotInitializerList { |
202 | | typedef void type; |
203 | | }; |
204 | | template <typename T> |
205 | | struct IsNotInitializerList<std::initializer_list<T> > {}; |
206 | | #endif // LANG_CXX11 |
207 | | |
208 | | // This class implements the behavior of the split API by giving callers access |
209 | | // to the underlying split substrings in various convenient ways, such as |
210 | | // through iterators or implicit conversion functions. Do not construct this |
211 | | // class directly, rather use the Split() function instead. |
212 | | // |
213 | | // Output containers can be collections of either GStringPiece or string objects. |
214 | | // GStringPiece is more efficient because the underlying data will not need to be |
215 | | // copied; the returned GStringPieces will all refer to the data within the |
216 | | // original input string. If a collection of string objects is used, then each |
217 | | // substring will be copied. |
218 | | // |
219 | | // An optional Predicate functor may be supplied. This predicate will be used to |
220 | | // filter the split strings: only strings for which the predicate returns true |
221 | | // will be kept. A Predicate object is any unary functor that takes a |
222 | | // GStringPiece and returns bool. By default, the NoFilter predicate is used, |
223 | | // which does not filter out anything. |
224 | | template <typename Delimiter, typename Predicate = NoFilter> |
225 | | class Splitter { |
226 | | public: |
227 | | typedef internal::SplitIterator<Delimiter, Predicate> Iterator; |
228 | | |
229 | | Splitter(GStringPiece text, Delimiter d) |
230 | 222k | : begin_(text, d), end_(d) {} strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::Splitter(GStringPiece, strings::delimiter::Literal) Line | Count | Source | 230 | 222k | : begin_(text, d), end_(d) {} |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::Splitter(GStringPiece, strings::delimiter::AnyOf) Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::Splitter(GStringPiece, strings::delimiter::LimitImpl<strings::delimiter::AnyOf>) |
231 | | |
232 | | Splitter(GStringPiece text, Delimiter d, Predicate p) |
233 | 332k | : begin_(text, d, p), end_(d, p) {} strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::Splitter(GStringPiece, strings::delimiter::Literal, strings::SkipEmpty) Line | Count | Source | 233 | 332k | : begin_(text, d, p), end_(d, p) {} |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::Splitter(GStringPiece, strings::delimiter::AnyOf, strings::SkipEmpty) strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::Splitter(GStringPiece, strings::delimiter::Literal, strings::AllowEmpty) Line | Count | Source | 233 | 101 | : begin_(text, d, p), end_(d, p) {} |
|
234 | | |
235 | | // Range functions that iterate the split substrings as GStringPiece objects. |
236 | | // These methods enable a Splitter to be used in a range-based for loop in |
237 | | // C++11, for example: |
238 | | // |
239 | | // for (GStringPiece sp : my_splitter) { |
240 | | // DoWork(sp); |
241 | | // } |
242 | 554k | const Iterator& begin() const { return begin_; } strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::begin() const Line | Count | Source | 242 | 332k | const Iterator& begin() const { return begin_; } |
strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::begin() const Line | Count | Source | 242 | 222k | const Iterator& begin() const { return begin_; } |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::begin() const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::begin() const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::begin() const strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::begin() const Line | Count | Source | 242 | 101 | const Iterator& begin() const { return begin_; } |
|
243 | 0 | const Iterator& end() const { return end_; } |
244 | | |
245 | | #ifdef LANG_CXX11 |
246 | | // Support for default template arguments for function templates was added in |
247 | | // C++11, but it is not allowed if compiled in C++98 compatibility mode. Since |
248 | | // this code is under a LANG_CXX11 guard, we can safely ignore the |
249 | | // -Wc++98-compat flag and use default template arguments on the implicit |
250 | | // conversion operator below. |
251 | | // |
252 | | // This use of default template arguments on a function template was approved |
253 | | // by tgs and sanjay on behalf of the c-style-arbiters in email thread |
254 | | // |
255 | | // All compiler flags are first saved with a diagnostic push and restored with a |
256 | | // diagnostic pop below. |
257 | | #pragma GCC diagnostic push |
258 | | #pragma GCC diagnostic ignored "-Wpragmas" |
259 | | #pragma GCC diagnostic ignored "-Wc++98-compat" |
260 | | |
261 | | // Uses SFINAE to restrict conversion to container-like types (by testing for |
262 | | // the presence of a const_iterator member type) and also to disable |
263 | | // conversion to an initializer_list (which also has a const_iterator). |
264 | | // Otherwise, code compiled in C++11 will get an error due to ambiguous |
265 | | // conversion paths (in C++11 vector<T>::operator= is overloaded to take |
266 | | // either a vector<T> or an initializer_list<T>). |
267 | | // |
268 | | // This trick was taken from util/gtl/container_literal.h |
269 | | template <typename Container, |
270 | | typename IsNotInitializerListChecker = |
271 | | typename IsNotInitializerList<Container>::type, |
272 | | typename ContainerChecker = |
273 | | typename Container::const_iterator> |
274 | 554k | operator Container() { |
275 | 554k | return SelectContainer<Container, is_map<Container>::value>()(this); |
276 | 554k | } strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::operator std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >() Line | Count | Source | 274 | 332k | operator Container() { | 275 | 332k | return SelectContainer<Container, is_map<Container>::value>()(this); | 276 | 332k | } |
strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::operator std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >() Line | Count | Source | 274 | 220k | operator Container() { | 275 | 220k | return SelectContainer<Container, is_map<Container>::value>()(this); | 276 | 220k | } |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::operator std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> ><std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, void, std::__1::__wrap_iter<GStringPiece const*> >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::operator std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> ><std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, void, std::__1::__wrap_iter<GStringPiece const*> >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::operator std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__tree_const_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__tree_node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void*>*, long> >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::operator std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > ><std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, void, std::__1::__map_const_iterator<std::__1::__tree_const_iterator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void*>*, long> > >() Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::operator std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> ><std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, void, std::__1::__wrap_iter<GStringPiece const*> >() strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::operator std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> ><std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, void, std::__1::__wrap_iter<GStringPiece const*> >() Line | Count | Source | 274 | 1.27k | operator Container() { | 275 | 1.27k | return SelectContainer<Container, is_map<Container>::value>()(this); | 276 | 1.27k | } |
strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::operator std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >() Line | Count | Source | 274 | 101 | operator Container() { | 275 | 101 | return SelectContainer<Container, is_map<Container>::value>()(this); | 276 | 101 | } |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::operator std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > ><std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, void, std::__1::__list_const_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void*> >() |
277 | | |
278 | | // Restores diagnostic settings, i.e., removes the "ignore" on -Wpragmas and |
279 | | // -Wc++98-compat. |
280 | | #pragma GCC diagnostic pop |
281 | | |
282 | | #else |
283 | | // Not under LANG_CXX11 |
284 | | template <typename Container> |
285 | | operator Container() { |
286 | | return SelectContainer<Container, is_map<Container>::value>()(this); |
287 | | } |
288 | | #endif // LANG_CXX11 |
289 | | |
290 | | template <typename First, typename Second> |
291 | | operator std::pair<First, Second>() { |
292 | | return ToPair<First, Second>(); |
293 | | } |
294 | | |
295 | | private: |
296 | | // is_map<T>::value is true iff there exists a type T::mapped_type. This is |
297 | | // used to dispatch to one of the SelectContainer<> functors (below) from the |
298 | | // implicit conversion operator (above). |
299 | | template <typename T> |
300 | | struct is_map { |
301 | | template <typename U> static base::big_ test(typename U::mapped_type*); |
302 | | template <typename> static base::small_ test(...); |
303 | | static const bool value = (sizeof(test<T>(0)) == sizeof(base::big_)); |
304 | | }; |
305 | | |
306 | | // Base template handles splitting to non-map containers |
307 | | template <typename Container, bool> |
308 | | struct SelectContainer { |
309 | 554k | Container operator()(Splitter* splitter) const { |
310 | 554k | return splitter->template ToContainer<Container>(); |
311 | 554k | } strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::SelectContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>*) const Line | Count | Source | 309 | 332k | Container operator()(Splitter* splitter) const { | 310 | 332k | return splitter->template ToContainer<Container>(); | 311 | 332k | } |
strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::SelectContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>*) const Line | Count | Source | 309 | 220k | Container operator()(Splitter* splitter) const { | 310 | 220k | return splitter->template ToContainer<Container>(); | 311 | 220k | } |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::SelectContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>*) const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::SelectContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, false>::operator()(strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>*) const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::SelectContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>*) const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::SelectContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, false>::operator()(strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>*) const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::SelectContainer<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>*) const Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::SelectContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, false>::operator()(strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>*) const strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::SelectContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> >, false>::operator()(strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>*) const Line | Count | Source | 309 | 1.27k | Container operator()(Splitter* splitter) const { | 310 | 1.27k | return splitter->template ToContainer<Container>(); | 311 | 1.27k | } |
strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::SelectContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>*) const Line | Count | Source | 309 | 101 | Container operator()(Splitter* splitter) const { | 310 | 101 | return splitter->template ToContainer<Container>(); | 311 | 101 | } |
Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::SelectContainer<std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, false>::operator()(strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>*) const |
312 | | }; |
313 | | |
314 | | // Partial template specialization for splitting to map-like containers. |
315 | | template <typename Container> |
316 | | struct SelectContainer<Container, true> { |
317 | 0 | Container operator()(Splitter* splitter) const { |
318 | 0 | return splitter->template ToMap<Container>(); |
319 | 0 | } |
320 | | }; |
321 | | |
322 | | // Inserts split results into the container. To do this the results are first |
323 | | // stored in a vector<GStringPiece>. This is where the input text is actually |
324 | | // "parsed". This vector is then used to possibly reserve space in the output |
325 | | // container, and the GStringPieces in "v" are converted as necessary to the |
326 | | // output container's value type. |
327 | | // |
328 | | // The reason to use an intermediate vector of GStringPiece is so we can learn |
329 | | // the needed capacity of the output container. This is needed when the output |
330 | | // container is a vector<string> in which case resizes can be expensive due to |
331 | | // copying of the ::string objects. |
332 | | // |
333 | | // At some point in the future we might add a C++11 move constructor to |
334 | | // ::string, in which case the vector resizes are much less expensive and the |
335 | | // use of this intermediate vector "v" can be removed. |
336 | | template <typename Container> |
337 | 554k | Container ToContainer() { |
338 | 554k | vector<GStringPiece> v; |
339 | 1.75M | for (Iterator it = begin(); it != end_; ++it1.20M ) { |
340 | 1.20M | v.push_back(*it); |
341 | 1.20M | } |
342 | 554k | typedef typename Container::value_type ToType; |
343 | 554k | internal::GStringPieceTo<ToType> converter; |
344 | 554k | Container c; |
345 | 554k | ReserveCapacity(&c, v.size()); |
346 | 554k | std::insert_iterator<Container> inserter(c, c.begin()); |
347 | 1.20M | for (const auto& sp : v) { |
348 | 1.20M | *inserter++ = converter(sp); |
349 | 1.20M | } |
350 | 554k | return c; |
351 | 554k | } std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::ToContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Line | Count | Source | 337 | 332k | Container ToContainer() { | 338 | 332k | vector<GStringPiece> v; | 339 | 731k | for (Iterator it = begin(); it != end_; ++it399k ) { | 340 | 399k | v.push_back(*it); | 341 | 399k | } | 342 | 332k | typedef typename Container::value_type ToType; | 343 | 332k | internal::GStringPieceTo<ToType> converter; | 344 | 332k | Container c; | 345 | 332k | ReserveCapacity(&c, v.size()); | 346 | 332k | std::insert_iterator<Container> inserter(c, c.begin()); | 347 | 398k | for (const auto& sp : v) { | 348 | 398k | *inserter++ = converter(sp); | 349 | 398k | } | 350 | 332k | return c; | 351 | 332k | } |
std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::ToContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Line | Count | Source | 337 | 220k | Container ToContainer() { | 338 | 220k | vector<GStringPiece> v; | 339 | 1.02M | for (Iterator it = begin(); it != end_; ++it799k ) { | 340 | 799k | v.push_back(*it); | 341 | 799k | } | 342 | 220k | typedef typename Container::value_type ToType; | 343 | 220k | internal::GStringPieceTo<ToType> converter; | 344 | 220k | Container c; | 345 | 220k | ReserveCapacity(&c, v.size()); | 346 | 220k | std::insert_iterator<Container> inserter(c, c.begin()); | 347 | 799k | for (const auto& sp : v) { | 348 | 799k | *inserter++ = converter(sp); | 349 | 799k | } | 350 | 220k | return c; | 351 | 220k | } |
Unexecuted instantiation: std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::ToContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Unexecuted instantiation: std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::ToContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > >() Unexecuted instantiation: std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::ToContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Unexecuted instantiation: std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::ToContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > >() Unexecuted instantiation: std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::ToContainer<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Unexecuted instantiation: std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::ToContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > >() std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::ToContainer<std::__1::vector<GStringPiece, std::__1::allocator<GStringPiece> > >() Line | Count | Source | 337 | 1.27k | Container ToContainer() { | 338 | 1.27k | vector<GStringPiece> v; | 339 | 3.18k | for (Iterator it = begin(); it != end_; ++it1.90k ) { | 340 | 1.90k | v.push_back(*it); | 341 | 1.90k | } | 342 | 1.27k | typedef typename Container::value_type ToType; | 343 | 1.27k | internal::GStringPieceTo<ToType> converter; | 344 | 1.27k | Container c; | 345 | 1.27k | ReserveCapacity(&c, v.size()); | 346 | 1.27k | std::insert_iterator<Container> inserter(c, c.begin()); | 347 | 1.90k | for (const auto& sp : v) { | 348 | 1.90k | *inserter++ = converter(sp); | 349 | 1.90k | } | 350 | 1.27k | return c; | 351 | 1.27k | } |
std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::ToContainer<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() Line | Count | Source | 337 | 101 | Container ToContainer() { | 338 | 101 | vector<GStringPiece> v; | 339 | 313 | for (Iterator it = begin(); it != end_; ++it212 ) { | 340 | 212 | v.push_back(*it); | 341 | 212 | } | 342 | 101 | typedef typename Container::value_type ToType; | 343 | 101 | internal::GStringPieceTo<ToType> converter; | 344 | 101 | Container c; | 345 | 101 | ReserveCapacity(&c, v.size()); | 346 | 101 | std::insert_iterator<Container> inserter(c, c.begin()); | 347 | 212 | for (const auto& sp : v) { | 348 | 212 | *inserter++ = converter(sp); | 349 | 212 | } | 350 | 101 | return c; | 351 | 101 | } |
Unexecuted instantiation: std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::ToContainer<std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >() |
352 | | |
353 | | // The algorithm is to insert a new pair into the map for each even-numbered |
354 | | // item, with the even-numbered item as the key with a default-constructed |
355 | | // value. Each odd-numbered item will then be assigned to the last pair's |
356 | | // value. |
357 | | template <typename Map> |
358 | 0 | Map ToMap() { |
359 | 0 | typedef typename Map::key_type Key; |
360 | 0 | typedef typename Map::mapped_type Data; |
361 | 0 | Map m; |
362 | 0 | GStringPieceTo<Key> key_converter; |
363 | 0 | GStringPieceTo<Data> val_converter; |
364 | 0 | typename Map::iterator curr_pair; |
365 | 0 | bool is_even = true; |
366 | 0 | for (Iterator it = begin(); it != end_; ++it) { |
367 | 0 | if (is_even) { |
368 | 0 | curr_pair = InsertInMap(std::make_pair(key_converter(*it), Data()), &m); |
369 | 0 | } else { |
370 | 0 | curr_pair->second = val_converter(*it); |
371 | 0 | } |
372 | 0 | is_even = !is_even; |
373 | 0 | } |
374 | 0 | return m; |
375 | 0 | } |
376 | | |
377 | | // Returns a pair with its .first and .second members set to the first two |
378 | | // strings returned by the begin() iterator. Either/both of .first and .second |
379 | | // will be empty strings if the iterator doesn't have a corresponding value. |
380 | | template <typename First, typename Second> |
381 | | std::pair<First, Second> ToPair() { |
382 | | GStringPieceTo<First> first_converter; |
383 | | GStringPieceTo<Second> second_converter; |
384 | | GStringPiece first, second; |
385 | | Iterator it = begin(); |
386 | | if (it != end()) { |
387 | | first = *it; |
388 | | if (++it != end()) { |
389 | | second = *it; |
390 | | } |
391 | | } |
392 | | return std::make_pair(first_converter(first), second_converter(second)); |
393 | | } |
394 | | |
395 | | // Overloaded InsertInMap() function. The first overload is the commonly used |
396 | | // one for most map-like objects. The second overload is a special case for |
397 | | // multimap, because multimap's insert() member function directly returns an |
398 | | // iterator, rather than a pair<iterator, bool> like map's. |
399 | | template <typename Map> |
400 | | typename Map::iterator InsertInMap( |
401 | 0 | const typename Map::value_type& value, Map* map) { |
402 | 0 | return map->insert(value).first; |
403 | 0 | } |
404 | | |
405 | | // InsertInMap overload for multimap. |
406 | | template <typename K, typename T, typename C, typename A> |
407 | | typename std::multimap<K, T, C, A>::iterator InsertInMap( |
408 | | const typename std::multimap<K, T, C, A>::value_type& value, |
409 | | typename std::multimap<K, T, C, A>* map) { |
410 | | return map->insert(value); |
411 | | } |
412 | | |
413 | | // Reserves the given amount of capacity in a vector<string> |
414 | | template <typename A> |
415 | 553k | void ReserveCapacity(vector<string, A>* v, size_t size) { |
416 | 553k | v->reserve(size); |
417 | 553k | } void strings::internal::Splitter<strings::delimiter::Literal, strings::SkipEmpty>::ReserveCapacity<std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) Line | Count | Source | 415 | 332k | void ReserveCapacity(vector<string, A>* v, size_t size) { | 416 | 332k | v->reserve(size); | 417 | 332k | } |
void strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::ReserveCapacity<std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) Line | Count | Source | 415 | 220k | void ReserveCapacity(vector<string, A>* v, size_t size) { | 416 | 220k | v->reserve(size); | 417 | 220k | } |
Unexecuted instantiation: void strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::ReserveCapacity<std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) Unexecuted instantiation: void strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::ReserveCapacity<std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) void strings::internal::Splitter<strings::delimiter::Literal, strings::AllowEmpty>::ReserveCapacity<std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >*, unsigned long) Line | Count | Source | 415 | 101 | void ReserveCapacity(vector<string, A>* v, size_t size) { | 416 | 101 | v->reserve(size); | 417 | 101 | } |
|
418 | 1.27k | void ReserveCapacity(...) {} Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::internal::NoFilter>::ReserveCapacity(...) Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::LimitImpl<strings::delimiter::AnyOf>, strings::internal::NoFilter>::ReserveCapacity(...) Unexecuted instantiation: strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::ReserveCapacity(...) strings::internal::Splitter<strings::delimiter::Literal, strings::internal::NoFilter>::ReserveCapacity(...) Line | Count | Source | 418 | 1.27k | void ReserveCapacity(...) {} |
|
419 | | |
420 | | const Iterator begin_; |
421 | | const Iterator end_; |
422 | | }; |
423 | | |
424 | | } // namespace internal |
425 | | |
426 | | } // namespace strings |
427 | | |
428 | | #endif // YB_GUTIL_STRINGS_SPLIT_INTERNAL_H |