YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
555k
  bool operator()(GStringPiece /* ignored */) {
59
555k
    return true;
60
555k
  }
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
158k
      : delimiter_(std::move(d)), predicate_(), is_end_(true) {}
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEC2ES3_
Line
Count
Source
90
158k
      : delimiter_(std::move(d)), predicate_(), is_end_(true) {}
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEC2ES3_
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEC2ES5_
91
  SplitIterator(Delimiter d, Predicate p)
92
213k
      : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {}
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEC2ES3_S4_
Line
Count
Source
92
213k
      : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {}
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEC2ES3_S4_
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEC2ES3_S4_
Line
Count
Source
92
99
      : 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
158k
        is_end_(false) {
99
158k
    ++(*this);
100
158k
  }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEC2E12GStringPieceS3_
Line
Count
Source
98
158k
        is_end_(false) {
99
158k
    ++(*this);
100
158k
  }
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEC2E12GStringPieceS3_
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEC2E12GStringPieceS5_
101
  SplitIterator(GStringPiece text, Delimiter d, Predicate p)
102
      : text_(std::move(text)),
103
        delimiter_(std::move(d)),
104
        predicate_(std::move(p)),
105
213k
        is_end_(false) {
106
213k
    ++(*this);
107
213k
  }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEC2E12GStringPieceS3_S4_
Line
Count
Source
105
213k
        is_end_(false) {
106
213k
    ++(*this);
107
213k
  }
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEC2E12GStringPieceS3_S4_
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEC2E12GStringPieceS3_S4_
Line
Count
Source
105
99
        is_end_(false) {
106
99
    ++(*this);
107
99
  }
108
109
819k
  GStringPiece operator*() { return curr_piece_; }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEdeEv
Line
Count
Source
109
555k
  GStringPiece operator*() { return curr_piece_; }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEdeEv
Line
Count
Source
109
264k
  GStringPiece operator*() { return curr_piece_; }
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEdeEv
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEdeEv
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEdeEv
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEdeEv
Line
Count
Source
109
208
  GStringPiece operator*() { return curr_piece_; }
110
0
  GStringPiece* operator->() { return &curr_piece_; }
111
112
1.19M
  SplitIterator& operator++() {
113
1.19M
    do {
114
1.19M
      if (text_.end() == curr_piece_.end()) {
115
        // Already consumed all of text_, so we're done.
116
372k
        is_end_ = true;
117
372k
        return *this;
118
372k
      }
119
825k
      GStringPiece found_delimiter = delimiter_.Find(text_);
120
825k
      assert(found_delimiter.data() != NULL);
121
825k
      assert(text_.begin() <= found_delimiter.begin());
122
825k
      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
825k
      curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin());
127
825k
      text_.remove_prefix(found_delimiter.end() - text_.begin());
128
825k
    } while (!predicate_(curr_piece_));
129
819k
    return *this;
130
1.19M
  }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEppEv
Line
Count
Source
112
714k
  SplitIterator& operator++() {
113
714k
    do {
114
714k
      if (text_.end() == curr_piece_.end()) {
115
        // Already consumed all of text_, so we're done.
116
158k
        is_end_ = true;
117
158k
        return *this;
118
158k
      }
119
555k
      GStringPiece found_delimiter = delimiter_.Find(text_);
120
555k
      assert(found_delimiter.data() != NULL);
121
555k
      assert(text_.begin() <= found_delimiter.begin());
122
555k
      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
555k
      curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin());
127
555k
      text_.remove_prefix(found_delimiter.end() - text_.begin());
128
555k
    } while (!predicate_(curr_piece_));
129
555k
    return *this;
130
714k
  }
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEppEv
Line
Count
Source
112
477k
  SplitIterator& operator++() {
113
483k
    do {
114
483k
      if (text_.end() == curr_piece_.end()) {
115
        // Already consumed all of text_, so we're done.
116
213k
        is_end_ = true;
117
213k
        return *this;
118
213k
      }
119
270k
      GStringPiece found_delimiter = delimiter_.Find(text_);
120
270k
      assert(found_delimiter.data() != NULL);
121
270k
      assert(text_.begin() <= found_delimiter.begin());
122
270k
      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
270k
      curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin());
127
270k
      text_.remove_prefix(found_delimiter.end() - text_.begin());
128
270k
    } while (!predicate_(curr_piece_));
129
264k
    return *this;
130
477k
  }
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEppEv
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEppEv
Unexecuted instantiation: _ZN7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEppEv
_ZN7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEppEv
Line
Count
Source
112
307
  SplitIterator& operator++() {
113
307
    do {
114
307
      if (text_.end() == curr_piece_.end()) {
115
        // Already consumed all of text_, so we're done.
116
99
        is_end_ = true;
117
99
        return *this;
118
99
      }
119
208
      GStringPiece found_delimiter = delimiter_.Find(text_);
120
208
      assert(found_delimiter.data() != NULL);
121
208
      assert(text_.begin() <= found_delimiter.begin());
122
208
      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
208
      curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin());
127
208
      text_.remove_prefix(found_delimiter.end() - text_.begin());
128
208
    } while (!predicate_(curr_piece_));
129
208
    return *this;
130
307
  }
131
132
  SplitIterator operator++(int /* postincrement */) {
133
    SplitIterator old(*this);
134
    ++(*this);
135
    return old;
136
  }
137
138
1.19M
  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.19M
    return (is_end_ && other.is_end_) ||
146
819k
           (is_end_ == other.is_end_ &&
147
0
            text_ == other.text_ &&
148
0
            text_.data() == other.text_.data() &&
149
0
            curr_piece_ == other.curr_piece_ &&
150
0
            curr_piece_.data() == other.curr_piece_.data());
151
1.19M
  }
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEeqERKS5_
Line
Count
Source
138
714k
  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
714k
    return (is_end_ && other.is_end_) ||
146
555k
           (is_end_ == other.is_end_ &&
147
0
            text_ == other.text_ &&
148
0
            text_.data() == other.text_.data() &&
149
0
            curr_piece_ == other.curr_piece_ &&
150
0
            curr_piece_.data() == other.curr_piece_.data());
151
714k
  }
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEeqERKS5_
Line
Count
Source
138
477k
  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
477k
    return (is_end_ && other.is_end_) ||
146
264k
           (is_end_ == other.is_end_ &&
147
0
            text_ == other.text_ &&
148
0
            text_.data() == other.text_.data() &&
149
0
            curr_piece_ == other.curr_piece_ &&
150
0
            curr_piece_.data() == other.curr_piece_.data());
151
477k
  }
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEeqERKS5_
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEeqERKS7_
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEeqERKS5_
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEeqERKS5_
Line
Count
Source
138
307
  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
307
    return (is_end_ && other.is_end_) ||
146
208
           (is_end_ == other.is_end_ &&
147
0
            text_ == other.text_ &&
148
0
            text_.data() == other.text_.data() &&
149
0
            curr_piece_ == other.curr_piece_ &&
150
0
            curr_piece_.data() == other.curr_piece_.data());
151
307
  }
152
153
1.19M
  bool operator!=(const SplitIterator& other) const {
154
1.19M
    return !(*this == other);
155
1.19M
  }
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS0_8NoFilterEEneERKS5_
Line
Count
Source
153
714k
  bool operator!=(const SplitIterator& other) const {
154
714k
    return !(*this == other);
155
714k
  }
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_9SkipEmptyEEneERKS5_
Line
Count
Source
153
477k
  bool operator!=(const SplitIterator& other) const {
154
477k
    return !(*this == other);
155
477k
  }
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS0_8NoFilterEEneERKS5_
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEneERKS7_
Unexecuted instantiation: _ZNK7strings8internal13SplitIteratorINS_9delimiter5AnyOfENS_9SkipEmptyEEneERKS5_
_ZNK7strings8internal13SplitIteratorINS_9delimiter7LiteralENS_10AllowEmptyEEneERKS5_
Line
Count
Source
153
307
  bool operator!=(const SplitIterator& other) const {
154
307
    return !(*this == other);
155
307
  }
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
709
  To operator()(GStringPiece from) const {
177
709
    return To(from);
178
709
  }
179
};
180
181
// Specialization for converting to string.
182
template <>
183
struct GStringPieceTo<string> {
184
819k
  string operator()(GStringPiece from) const {
185
819k
    return from.ToString();
186
819k
  }
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
158k
      : begin_(text, d), end_(d) {}
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEEC2E12GStringPieceS3_
Line
Count
Source
230
158k
      : begin_(text, d), end_(d) {}
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEEC2E12GStringPieceS3_
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEC2E12GStringPieceS5_
231
232
  Splitter(GStringPiece text, Delimiter d, Predicate p)
233
213k
      : begin_(text, d, p), end_(d, p) {}
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEEC2E12GStringPieceS3_S4_
Line
Count
Source
233
213k
      : begin_(text, d, p), end_(d, p) {}
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEC2E12GStringPieceS3_S4_
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEEC2E12GStringPieceS3_S4_
Line
Count
Source
233
99
      : 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
372k
  const Iterator& begin() const { return begin_; }
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE5beginEv
Line
Count
Source
242
158k
  const Iterator& begin() const { return begin_; }
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEE5beginEv
Line
Count
Source
242
213k
  const Iterator& begin() const { return begin_; }
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE5beginEv
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE5beginEv
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE5beginEv
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEE5beginEv
Line
Count
Source
242
99
  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
372k
  operator Container() {
275
372k
    return SelectContainer<Container, is_map<Container>::value>()(this);
276
372k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEEcvT_INSt3__16vectorINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENSD_ISF_EEEEvNS8_11__wrap_iterIPKSF_EEEEv
Line
Count
Source
274
158k
  operator Container() {
275
158k
    return SelectContainer<Container, is_map<Container>::value>()(this);
276
158k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEEcvT_INSt3__16vectorINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENSD_ISF_EEEEvNS8_11__wrap_iterIPKSF_EEEEv
Line
Count
Source
274
213k
  operator Container() {
275
213k
    return SelectContainer<Container, is_map<Container>::value>()(this);
276
213k
  }
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEEcvT_INSt3__16vectorINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENSD_ISF_EEEEvNS8_11__wrap_iterIPKSF_EEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEEcvT_INSt3__16vectorI12GStringPieceNS8_9allocatorISA_EEEEvNS8_11__wrap_iterIPKSA_EEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEcvT_INSt3__16vectorINSA_12basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEENSF_ISH_EEEEvNSA_11__wrap_iterIPKSH_EEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEEcvT_INSt3__16vectorI12GStringPieceNSA_9allocatorISC_EEEEvNSA_11__wrap_iterIPKSC_EEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEcvT_INSt3__13setINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENS8_4lessISF_EENSD_ISF_EEEEvNS8_21__tree_const_iteratorISF_PNS8_11__tree_nodeISF_PvEElEEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEcvT_INSt3__13mapINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESF_NS8_4lessISF_EENSD_INS8_4pairIKSF_SF_EEEEEEvNS8_20__map_const_iteratorINS8_21__tree_const_iteratorINS8_12__value_typeISF_SF_EEPNS8_11__tree_nodeISQ_PvEElEEEEEEv
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEcvT_INSt3__16vectorI12GStringPieceNS8_9allocatorISA_EEEEvNS8_11__wrap_iterIPKSA_EEEEv
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEEcvT_INSt3__16vectorI12GStringPieceNS8_9allocatorISA_EEEEvNS8_11__wrap_iterIPKSA_EEEEv
Line
Count
Source
274
473
  operator Container() {
275
473
    return SelectContainer<Container, is_map<Container>::value>()(this);
276
473
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEEcvT_INSt3__16vectorINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENSD_ISF_EEEEvNS8_11__wrap_iterIPKSF_EEEEv
Line
Count
Source
274
99
  operator Container() {
275
99
    return SelectContainer<Container, is_map<Container>::value>()(this);
276
99
  }
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEEcvT_INSt3__14listINS8_12basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEENSD_ISF_EEEEvNS8_21__list_const_iteratorISF_PvEEEEv
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
372k
    Container operator()(Splitter* splitter) const {
310
372k
      return splitter->template ToContainer<Container>();
311
372k
    }
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE15SelectContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEELb0EEclEPS5_
Line
Count
Source
309
158k
    Container operator()(Splitter* splitter) const {
310
158k
      return splitter->template ToContainer<Container>();
311
158k
    }
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEE15SelectContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEELb0EEclEPS5_
Line
Count
Source
309
213k
    Container operator()(Splitter* splitter) const {
310
213k
      return splitter->template ToContainer<Container>();
311
213k
    }
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE15SelectContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEELb0EEclEPS5_
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE15SelectContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEELb0EEclEPS5_
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE15SelectContainerINSt3__16vectorINS9_12basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEENSE_ISG_EEEELb0EEclEPS7_
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE15SelectContainerINSt3__16vectorI12GStringPieceNS9_9allocatorISB_EEEELb0EEclEPS7_
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE15SelectContainerINSt3__13setINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENS7_4lessISE_EENSC_ISE_EEEELb0EEclEPS5_
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE15SelectContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEELb0EEclEPS5_
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE15SelectContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEELb0EEclEPS5_
Line
Count
Source
309
473
    Container operator()(Splitter* splitter) const {
310
473
      return splitter->template ToContainer<Container>();
311
473
    }
_ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEE15SelectContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEELb0EEclEPS5_
Line
Count
Source
309
99
    Container operator()(Splitter* splitter) const {
310
99
      return splitter->template ToContainer<Container>();
311
99
    }
Unexecuted instantiation: _ZNK7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE15SelectContainerINSt3__14listINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEELb0EEclEPS5_
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
372k
  Container ToContainer() {
338
372k
    vector<GStringPiece> v;
339
1.19M
    for (Iterator it = begin(); it != end_; ++it) {
340
819k
      v.push_back(*it);
341
819k
    }
342
372k
    typedef typename Container::value_type ToType;
343
372k
    internal::GStringPieceTo<ToType> converter;
344
372k
    Container c;
345
372k
    ReserveCapacity(&c, v.size());
346
372k
    std::insert_iterator<Container> inserter(c, c.begin());
347
819k
    for (const auto& sp : v) {
348
819k
      *inserter++ = converter(sp);
349
819k
    }
350
372k
    return c;
351
372k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE11ToContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEEEET_v
Line
Count
Source
337
158k
  Container ToContainer() {
338
158k
    vector<GStringPiece> v;
339
713k
    for (Iterator it = begin(); it != end_; ++it) {
340
554k
      v.push_back(*it);
341
554k
    }
342
158k
    typedef typename Container::value_type ToType;
343
158k
    internal::GStringPieceTo<ToType> converter;
344
158k
    Container c;
345
158k
    ReserveCapacity(&c, v.size());
346
158k
    std::insert_iterator<Container> inserter(c, c.begin());
347
554k
    for (const auto& sp : v) {
348
554k
      *inserter++ = converter(sp);
349
554k
    }
350
158k
    return c;
351
158k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEE11ToContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEEEET_v
Line
Count
Source
337
213k
  Container ToContainer() {
338
213k
    vector<GStringPiece> v;
339
477k
    for (Iterator it = begin(); it != end_; ++it) {
340
264k
      v.push_back(*it);
341
264k
    }
342
213k
    typedef typename Container::value_type ToType;
343
213k
    internal::GStringPieceTo<ToType> converter;
344
213k
    Container c;
345
213k
    ReserveCapacity(&c, v.size());
346
213k
    std::insert_iterator<Container> inserter(c, c.begin());
347
264k
    for (const auto& sp : v) {
348
264k
      *inserter++ = converter(sp);
349
264k
    }
350
213k
    return c;
351
213k
  }
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE11ToContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEEEET_v
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE11ToContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEEEET_v
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE11ToContainerINSt3__16vectorINS9_12basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEENSE_ISG_EEEEEET_v
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE11ToContainerINSt3__16vectorI12GStringPieceNS9_9allocatorISB_EEEEEET_v
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE11ToContainerINSt3__13setINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENS7_4lessISE_EENSC_ISE_EEEEEET_v
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE11ToContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEEEET_v
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE11ToContainerINSt3__16vectorI12GStringPieceNS7_9allocatorIS9_EEEEEET_v
Line
Count
Source
337
473
  Container ToContainer() {
338
473
    vector<GStringPiece> v;
339
1.18k
    for (Iterator it = begin(); it != end_; ++it) {
340
709
      v.push_back(*it);
341
709
    }
342
473
    typedef typename Container::value_type ToType;
343
473
    internal::GStringPieceTo<ToType> converter;
344
473
    Container c;
345
473
    ReserveCapacity(&c, v.size());
346
473
    std::insert_iterator<Container> inserter(c, c.begin());
347
709
    for (const auto& sp : v) {
348
709
      *inserter++ = converter(sp);
349
709
    }
350
473
    return c;
351
473
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEE11ToContainerINSt3__16vectorINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEEEET_v
Line
Count
Source
337
99
  Container ToContainer() {
338
99
    vector<GStringPiece> v;
339
307
    for (Iterator it = begin(); it != end_; ++it) {
340
208
      v.push_back(*it);
341
208
    }
342
99
    typedef typename Container::value_type ToType;
343
99
    internal::GStringPieceTo<ToType> converter;
344
99
    Container c;
345
99
    ReserveCapacity(&c, v.size());
346
99
    std::insert_iterator<Container> inserter(c, c.begin());
347
208
    for (const auto& sp : v) {
348
208
      *inserter++ = converter(sp);
349
208
    }
350
99
    return c;
351
99
  }
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE11ToContainerINSt3__14listINS7_12basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEENSC_ISE_EEEEEET_v
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
372k
  void ReserveCapacity(vector<string, A>* v, size_t size) {
416
372k
    v->reserve(size);
417
372k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE15ReserveCapacityINSt3__19allocatorINS7_12basic_stringIcNS7_11char_traitsIcEENS8_IcEEEEEEEEvPNS7_6vectorISD_T_EEm
Line
Count
Source
415
158k
  void ReserveCapacity(vector<string, A>* v, size_t size) {
416
158k
    v->reserve(size);
417
158k
  }
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_9SkipEmptyEE15ReserveCapacityINSt3__19allocatorINS7_12basic_stringIcNS7_11char_traitsIcEENS8_IcEEEEEEEEvPNS7_6vectorISD_T_EEm
Line
Count
Source
415
213k
  void ReserveCapacity(vector<string, A>* v, size_t size) {
416
213k
    v->reserve(size);
417
213k
  }
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE15ReserveCapacityINSt3__19allocatorINS7_12basic_stringIcNS7_11char_traitsIcEENS8_IcEEEEEEEEvPNS7_6vectorISD_T_EEm
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE15ReserveCapacityINSt3__19allocatorINS9_12basic_stringIcNS9_11char_traitsIcEENSA_IcEEEEEEEEvPNS9_6vectorISF_T_EEm
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS_10AllowEmptyEE15ReserveCapacityINSt3__19allocatorINS7_12basic_stringIcNS7_11char_traitsIcEENS8_IcEEEEEEEEvPNS7_6vectorISD_T_EEm
Line
Count
Source
415
99
  void ReserveCapacity(vector<string, A>* v, size_t size) {
416
99
    v->reserve(size);
417
99
  }
418
473
  void ReserveCapacity(...) {}
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS0_8NoFilterEE15ReserveCapacityEz
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter9LimitImplINS2_5AnyOfEEENS0_8NoFilterEE15ReserveCapacityEz
Unexecuted instantiation: _ZN7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEE15ReserveCapacityEz
_ZN7strings8internal8SplitterINS_9delimiter7LiteralENS0_8NoFilterEE15ReserveCapacityEz
Line
Count
Source
418
473
  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