grpc 1.31.0.pre1 → 1.31.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +2 -2
- data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +3 -4
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +5 -4
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/third_party/re2/re2/bitmap256.h +117 -0
- data/third_party/re2/re2/bitstate.cc +385 -0
- data/third_party/re2/re2/compile.cc +1279 -0
- data/third_party/re2/re2/dfa.cc +2130 -0
- data/third_party/re2/re2/filtered_re2.cc +121 -0
- data/third_party/re2/re2/filtered_re2.h +109 -0
- data/third_party/re2/re2/mimics_pcre.cc +197 -0
- data/third_party/re2/re2/nfa.cc +713 -0
- data/third_party/re2/re2/onepass.cc +623 -0
- data/third_party/re2/re2/parse.cc +2464 -0
- data/third_party/re2/re2/perl_groups.cc +119 -0
- data/third_party/re2/re2/pod_array.h +55 -0
- data/third_party/re2/re2/prefilter.cc +710 -0
- data/third_party/re2/re2/prefilter.h +108 -0
- data/third_party/re2/re2/prefilter_tree.cc +407 -0
- data/third_party/re2/re2/prefilter_tree.h +139 -0
- data/third_party/re2/re2/prog.cc +988 -0
- data/third_party/re2/re2/prog.h +436 -0
- data/third_party/re2/re2/re2.cc +1362 -0
- data/third_party/re2/re2/re2.h +1002 -0
- data/third_party/re2/re2/regexp.cc +980 -0
- data/third_party/re2/re2/regexp.h +659 -0
- data/third_party/re2/re2/set.cc +154 -0
- data/third_party/re2/re2/set.h +80 -0
- data/third_party/re2/re2/simplify.cc +657 -0
- data/third_party/re2/re2/sparse_array.h +392 -0
- data/third_party/re2/re2/sparse_set.h +264 -0
- data/third_party/re2/re2/stringpiece.cc +65 -0
- data/third_party/re2/re2/stringpiece.h +210 -0
- data/third_party/re2/re2/tostring.cc +351 -0
- data/third_party/re2/re2/unicode_casefold.cc +582 -0
- data/third_party/re2/re2/unicode_casefold.h +78 -0
- data/third_party/re2/re2/unicode_groups.cc +6269 -0
- data/third_party/re2/re2/unicode_groups.h +67 -0
- data/third_party/re2/re2/walker-inl.h +246 -0
- data/third_party/re2/util/benchmark.h +156 -0
- data/third_party/re2/util/flags.h +26 -0
- data/third_party/re2/util/logging.h +109 -0
- data/third_party/re2/util/malloc_counter.h +19 -0
- data/third_party/re2/util/mix.h +41 -0
- data/third_party/re2/util/mutex.h +148 -0
- data/third_party/re2/util/pcre.cc +1025 -0
- data/third_party/re2/util/pcre.h +681 -0
- data/third_party/re2/util/rune.cc +260 -0
- data/third_party/re2/util/strutil.cc +149 -0
- data/third_party/re2/util/strutil.h +21 -0
- data/third_party/re2/util/test.h +50 -0
- data/third_party/re2/util/utf.h +44 -0
- data/third_party/re2/util/util.h +42 -0
- metadata +78 -29
@@ -0,0 +1,67 @@
|
|
1
|
+
// Copyright 2008 The RE2 Authors. All Rights Reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style
|
3
|
+
// license that can be found in the LICENSE file.
|
4
|
+
|
5
|
+
#ifndef RE2_UNICODE_GROUPS_H_
|
6
|
+
#define RE2_UNICODE_GROUPS_H_
|
7
|
+
|
8
|
+
// Unicode character groups.
|
9
|
+
|
10
|
+
// The codes get split into ranges of 16-bit codes
|
11
|
+
// and ranges of 32-bit codes. It would be simpler
|
12
|
+
// to use only 32-bit ranges, but these tables are large
|
13
|
+
// enough to warrant extra care.
|
14
|
+
//
|
15
|
+
// Using just 32-bit ranges gives 27 kB of data.
|
16
|
+
// Adding 16-bit ranges gives 18 kB of data.
|
17
|
+
// Adding an extra table of 16-bit singletons would reduce
|
18
|
+
// to 16.5 kB of data but make the data harder to use;
|
19
|
+
// we don't bother.
|
20
|
+
|
21
|
+
#include <stdint.h>
|
22
|
+
|
23
|
+
#include "util/util.h"
|
24
|
+
#include "util/utf.h"
|
25
|
+
|
26
|
+
namespace re2 {
|
27
|
+
|
28
|
+
struct URange16
|
29
|
+
{
|
30
|
+
uint16_t lo;
|
31
|
+
uint16_t hi;
|
32
|
+
};
|
33
|
+
|
34
|
+
struct URange32
|
35
|
+
{
|
36
|
+
Rune lo;
|
37
|
+
Rune hi;
|
38
|
+
};
|
39
|
+
|
40
|
+
struct UGroup
|
41
|
+
{
|
42
|
+
const char *name;
|
43
|
+
int sign; // +1 for [abc], -1 for [^abc]
|
44
|
+
const URange16 *r16;
|
45
|
+
int nr16;
|
46
|
+
const URange32 *r32;
|
47
|
+
int nr32;
|
48
|
+
};
|
49
|
+
|
50
|
+
// Named by property or script name (e.g., "Nd", "N", "Han").
|
51
|
+
// Negated groups are not included.
|
52
|
+
extern const UGroup unicode_groups[];
|
53
|
+
extern const int num_unicode_groups;
|
54
|
+
|
55
|
+
// Named by POSIX name (e.g., "[:alpha:]", "[:^lower:]").
|
56
|
+
// Negated groups are included.
|
57
|
+
extern const UGroup posix_groups[];
|
58
|
+
extern const int num_posix_groups;
|
59
|
+
|
60
|
+
// Named by Perl name (e.g., "\\d", "\\D").
|
61
|
+
// Negated groups are included.
|
62
|
+
extern const UGroup perl_groups[];
|
63
|
+
extern const int num_perl_groups;
|
64
|
+
|
65
|
+
} // namespace re2
|
66
|
+
|
67
|
+
#endif // RE2_UNICODE_GROUPS_H_
|
@@ -0,0 +1,246 @@
|
|
1
|
+
// Copyright 2006 The RE2 Authors. All Rights Reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style
|
3
|
+
// license that can be found in the LICENSE file.
|
4
|
+
|
5
|
+
#ifndef RE2_WALKER_INL_H_
|
6
|
+
#define RE2_WALKER_INL_H_
|
7
|
+
|
8
|
+
// Helper class for traversing Regexps without recursion.
|
9
|
+
// Clients should declare their own subclasses that override
|
10
|
+
// the PreVisit and PostVisit methods, which are called before
|
11
|
+
// and after visiting the subexpressions.
|
12
|
+
|
13
|
+
// Not quite the Visitor pattern, because (among other things)
|
14
|
+
// the Visitor pattern is recursive.
|
15
|
+
|
16
|
+
#include <stack>
|
17
|
+
|
18
|
+
#include "util/logging.h"
|
19
|
+
#include "re2/regexp.h"
|
20
|
+
|
21
|
+
namespace re2 {
|
22
|
+
|
23
|
+
template<typename T> struct WalkState;
|
24
|
+
|
25
|
+
template<typename T> class Regexp::Walker {
|
26
|
+
public:
|
27
|
+
Walker();
|
28
|
+
virtual ~Walker();
|
29
|
+
|
30
|
+
// Virtual method called before visiting re's children.
|
31
|
+
// PreVisit passes ownership of its return value to its caller.
|
32
|
+
// The Arg* that PreVisit returns will be passed to PostVisit as pre_arg
|
33
|
+
// and passed to the child PreVisits and PostVisits as parent_arg.
|
34
|
+
// At the top-most Regexp, parent_arg is arg passed to walk.
|
35
|
+
// If PreVisit sets *stop to true, the walk does not recurse
|
36
|
+
// into the children. Instead it behaves as though the return
|
37
|
+
// value from PreVisit is the return value from PostVisit.
|
38
|
+
// The default PreVisit returns parent_arg.
|
39
|
+
virtual T PreVisit(Regexp* re, T parent_arg, bool* stop);
|
40
|
+
|
41
|
+
// Virtual method called after visiting re's children.
|
42
|
+
// The pre_arg is the T that PreVisit returned.
|
43
|
+
// The child_args is a vector of the T that the child PostVisits returned.
|
44
|
+
// PostVisit takes ownership of pre_arg.
|
45
|
+
// PostVisit takes ownership of the Ts
|
46
|
+
// in *child_args, but not the vector itself.
|
47
|
+
// PostVisit passes ownership of its return value
|
48
|
+
// to its caller.
|
49
|
+
// The default PostVisit simply returns pre_arg.
|
50
|
+
virtual T PostVisit(Regexp* re, T parent_arg, T pre_arg,
|
51
|
+
T* child_args, int nchild_args);
|
52
|
+
|
53
|
+
// Virtual method called to copy a T,
|
54
|
+
// when Walk notices that more than one child is the same re.
|
55
|
+
virtual T Copy(T arg);
|
56
|
+
|
57
|
+
// Virtual method called to do a "quick visit" of the re,
|
58
|
+
// but not its children. Only called once the visit budget
|
59
|
+
// has been used up and we're trying to abort the walk
|
60
|
+
// as quickly as possible. Should return a value that
|
61
|
+
// makes sense for the parent PostVisits still to be run.
|
62
|
+
// This function is (hopefully) only called by
|
63
|
+
// WalkExponential, but must be implemented by all clients,
|
64
|
+
// just in case.
|
65
|
+
virtual T ShortVisit(Regexp* re, T parent_arg) = 0;
|
66
|
+
|
67
|
+
// Walks over a regular expression.
|
68
|
+
// Top_arg is passed as parent_arg to PreVisit and PostVisit of re.
|
69
|
+
// Returns the T returned by PostVisit on re.
|
70
|
+
T Walk(Regexp* re, T top_arg);
|
71
|
+
|
72
|
+
// Like Walk, but doesn't use Copy. This can lead to
|
73
|
+
// exponential runtimes on cross-linked Regexps like the
|
74
|
+
// ones generated by Simplify. To help limit this,
|
75
|
+
// at most max_visits nodes will be visited and then
|
76
|
+
// the walk will be cut off early.
|
77
|
+
// If the walk *is* cut off early, ShortVisit(re)
|
78
|
+
// will be called on regexps that cannot be fully
|
79
|
+
// visited rather than calling PreVisit/PostVisit.
|
80
|
+
T WalkExponential(Regexp* re, T top_arg, int max_visits);
|
81
|
+
|
82
|
+
// Clears the stack. Should never be necessary, since
|
83
|
+
// Walk always enters and exits with an empty stack.
|
84
|
+
// Logs DFATAL if stack is not already clear.
|
85
|
+
void Reset();
|
86
|
+
|
87
|
+
// Returns whether walk was cut off.
|
88
|
+
bool stopped_early() { return stopped_early_; }
|
89
|
+
|
90
|
+
private:
|
91
|
+
// Walk state for the entire traversal.
|
92
|
+
std::stack<WalkState<T>> stack_;
|
93
|
+
bool stopped_early_;
|
94
|
+
int max_visits_;
|
95
|
+
|
96
|
+
T WalkInternal(Regexp* re, T top_arg, bool use_copy);
|
97
|
+
|
98
|
+
Walker(const Walker&) = delete;
|
99
|
+
Walker& operator=(const Walker&) = delete;
|
100
|
+
};
|
101
|
+
|
102
|
+
template<typename T> T Regexp::Walker<T>::PreVisit(Regexp* re,
|
103
|
+
T parent_arg,
|
104
|
+
bool* stop) {
|
105
|
+
return parent_arg;
|
106
|
+
}
|
107
|
+
|
108
|
+
template<typename T> T Regexp::Walker<T>::PostVisit(Regexp* re,
|
109
|
+
T parent_arg,
|
110
|
+
T pre_arg,
|
111
|
+
T* child_args,
|
112
|
+
int nchild_args) {
|
113
|
+
return pre_arg;
|
114
|
+
}
|
115
|
+
|
116
|
+
template<typename T> T Regexp::Walker<T>::Copy(T arg) {
|
117
|
+
return arg;
|
118
|
+
}
|
119
|
+
|
120
|
+
// State about a single level in the traversal.
|
121
|
+
template<typename T> struct WalkState {
|
122
|
+
WalkState<T>(Regexp* re, T parent)
|
123
|
+
: re(re),
|
124
|
+
n(-1),
|
125
|
+
parent_arg(parent),
|
126
|
+
child_args(NULL) { }
|
127
|
+
|
128
|
+
Regexp* re; // The regexp
|
129
|
+
int n; // The index of the next child to process; -1 means need to PreVisit
|
130
|
+
T parent_arg; // Accumulated arguments.
|
131
|
+
T pre_arg;
|
132
|
+
T child_arg; // One-element buffer for child_args.
|
133
|
+
T* child_args;
|
134
|
+
};
|
135
|
+
|
136
|
+
template<typename T> Regexp::Walker<T>::Walker() {
|
137
|
+
stopped_early_ = false;
|
138
|
+
}
|
139
|
+
|
140
|
+
template<typename T> Regexp::Walker<T>::~Walker() {
|
141
|
+
Reset();
|
142
|
+
}
|
143
|
+
|
144
|
+
// Clears the stack. Should never be necessary, since
|
145
|
+
// Walk always enters and exits with an empty stack.
|
146
|
+
// Logs DFATAL if stack is not already clear.
|
147
|
+
template<typename T> void Regexp::Walker<T>::Reset() {
|
148
|
+
if (!stack_.empty()) {
|
149
|
+
LOG(DFATAL) << "Stack not empty.";
|
150
|
+
while (!stack_.empty()) {
|
151
|
+
delete[] stack_.top().child_args;
|
152
|
+
stack_.pop();
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
template<typename T> T Regexp::Walker<T>::WalkInternal(Regexp* re, T top_arg,
|
158
|
+
bool use_copy) {
|
159
|
+
Reset();
|
160
|
+
|
161
|
+
if (re == NULL) {
|
162
|
+
LOG(DFATAL) << "Walk NULL";
|
163
|
+
return top_arg;
|
164
|
+
}
|
165
|
+
|
166
|
+
stack_.push(WalkState<T>(re, top_arg));
|
167
|
+
|
168
|
+
WalkState<T>* s;
|
169
|
+
for (;;) {
|
170
|
+
T t;
|
171
|
+
s = &stack_.top();
|
172
|
+
Regexp* re = s->re;
|
173
|
+
switch (s->n) {
|
174
|
+
case -1: {
|
175
|
+
if (--max_visits_ < 0) {
|
176
|
+
stopped_early_ = true;
|
177
|
+
t = ShortVisit(re, s->parent_arg);
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
bool stop = false;
|
181
|
+
s->pre_arg = PreVisit(re, s->parent_arg, &stop);
|
182
|
+
if (stop) {
|
183
|
+
t = s->pre_arg;
|
184
|
+
break;
|
185
|
+
}
|
186
|
+
s->n = 0;
|
187
|
+
s->child_args = NULL;
|
188
|
+
if (re->nsub_ == 1)
|
189
|
+
s->child_args = &s->child_arg;
|
190
|
+
else if (re->nsub_ > 1)
|
191
|
+
s->child_args = new T[re->nsub_];
|
192
|
+
FALLTHROUGH_INTENDED;
|
193
|
+
}
|
194
|
+
default: {
|
195
|
+
if (re->nsub_ > 0) {
|
196
|
+
Regexp** sub = re->sub();
|
197
|
+
if (s->n < re->nsub_) {
|
198
|
+
if (use_copy && s->n > 0 && sub[s->n - 1] == sub[s->n]) {
|
199
|
+
s->child_args[s->n] = Copy(s->child_args[s->n - 1]);
|
200
|
+
s->n++;
|
201
|
+
} else {
|
202
|
+
stack_.push(WalkState<T>(sub[s->n], s->pre_arg));
|
203
|
+
}
|
204
|
+
continue;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
t = PostVisit(re, s->parent_arg, s->pre_arg, s->child_args, s->n);
|
209
|
+
if (re->nsub_ > 1)
|
210
|
+
delete[] s->child_args;
|
211
|
+
break;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
// We've finished stack_.top().
|
216
|
+
// Update next guy down.
|
217
|
+
stack_.pop();
|
218
|
+
if (stack_.empty())
|
219
|
+
return t;
|
220
|
+
s = &stack_.top();
|
221
|
+
if (s->child_args != NULL)
|
222
|
+
s->child_args[s->n] = t;
|
223
|
+
else
|
224
|
+
s->child_arg = t;
|
225
|
+
s->n++;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
template<typename T> T Regexp::Walker<T>::Walk(Regexp* re, T top_arg) {
|
230
|
+
// Without the exponential walking behavior,
|
231
|
+
// this budget should be more than enough for any
|
232
|
+
// regexp, and yet not enough to get us in trouble
|
233
|
+
// as far as CPU time.
|
234
|
+
max_visits_ = 1000000;
|
235
|
+
return WalkInternal(re, top_arg, true);
|
236
|
+
}
|
237
|
+
|
238
|
+
template<typename T> T Regexp::Walker<T>::WalkExponential(Regexp* re, T top_arg,
|
239
|
+
int max_visits) {
|
240
|
+
max_visits_ = max_visits;
|
241
|
+
return WalkInternal(re, top_arg, false);
|
242
|
+
}
|
243
|
+
|
244
|
+
} // namespace re2
|
245
|
+
|
246
|
+
#endif // RE2_WALKER_INL_H_
|
@@ -0,0 +1,156 @@
|
|
1
|
+
// Copyright 2009 The RE2 Authors. All Rights Reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style
|
3
|
+
// license that can be found in the LICENSE file.
|
4
|
+
|
5
|
+
#ifndef UTIL_BENCHMARK_H_
|
6
|
+
#define UTIL_BENCHMARK_H_
|
7
|
+
|
8
|
+
#include <stdint.h>
|
9
|
+
#include <functional>
|
10
|
+
|
11
|
+
#include "util/logging.h"
|
12
|
+
#include "util/util.h"
|
13
|
+
|
14
|
+
// Globals for the old benchmark API.
|
15
|
+
void StartBenchmarkTiming();
|
16
|
+
void StopBenchmarkTiming();
|
17
|
+
void SetBenchmarkBytesProcessed(int64_t b);
|
18
|
+
void SetBenchmarkItemsProcessed(int64_t i);
|
19
|
+
|
20
|
+
namespace benchmark {
|
21
|
+
|
22
|
+
// The new benchmark API implemented as a layer over the old benchmark API.
|
23
|
+
// (Please refer to https://github.com/google/benchmark for documentation.)
|
24
|
+
class State {
|
25
|
+
private:
|
26
|
+
class Iterator {
|
27
|
+
public:
|
28
|
+
// Benchmark code looks like this:
|
29
|
+
//
|
30
|
+
// for (auto _ : state) {
|
31
|
+
// // ...
|
32
|
+
// }
|
33
|
+
//
|
34
|
+
// We try to avoid compiler warnings about such variables being unused.
|
35
|
+
struct ATTRIBUTE_UNUSED Value {};
|
36
|
+
|
37
|
+
explicit Iterator(int64_t iters) : iters_(iters) {}
|
38
|
+
|
39
|
+
bool operator!=(const Iterator& that) const {
|
40
|
+
if (iters_ != that.iters_) {
|
41
|
+
return true;
|
42
|
+
} else {
|
43
|
+
// We are about to stop the loop, so stop timing.
|
44
|
+
StopBenchmarkTiming();
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
Value operator*() const {
|
50
|
+
return Value();
|
51
|
+
}
|
52
|
+
|
53
|
+
Iterator& operator++() {
|
54
|
+
--iters_;
|
55
|
+
return *this;
|
56
|
+
}
|
57
|
+
|
58
|
+
private:
|
59
|
+
int64_t iters_;
|
60
|
+
};
|
61
|
+
|
62
|
+
public:
|
63
|
+
explicit State(int64_t iters)
|
64
|
+
: iters_(iters), arg_(0), has_arg_(false) {}
|
65
|
+
|
66
|
+
State(int64_t iters, int64_t arg)
|
67
|
+
: iters_(iters), arg_(arg), has_arg_(true) {}
|
68
|
+
|
69
|
+
Iterator begin() {
|
70
|
+
// We are about to start the loop, so start timing.
|
71
|
+
StartBenchmarkTiming();
|
72
|
+
return Iterator(iters_);
|
73
|
+
}
|
74
|
+
|
75
|
+
Iterator end() {
|
76
|
+
return Iterator(0);
|
77
|
+
}
|
78
|
+
|
79
|
+
void SetBytesProcessed(int64_t b) { SetBenchmarkBytesProcessed(b); }
|
80
|
+
void SetItemsProcessed(int64_t i) { SetBenchmarkItemsProcessed(i); }
|
81
|
+
int64_t iterations() const { return iters_; }
|
82
|
+
// Pretend to support multiple arguments.
|
83
|
+
int64_t range(int pos) const { CHECK(has_arg_); return arg_; }
|
84
|
+
|
85
|
+
private:
|
86
|
+
int64_t iters_;
|
87
|
+
int64_t arg_;
|
88
|
+
bool has_arg_;
|
89
|
+
|
90
|
+
State(const State&) = delete;
|
91
|
+
State& operator=(const State&) = delete;
|
92
|
+
};
|
93
|
+
|
94
|
+
} // namespace benchmark
|
95
|
+
|
96
|
+
namespace testing {
|
97
|
+
|
98
|
+
class Benchmark {
|
99
|
+
public:
|
100
|
+
Benchmark(const char* name, void (*func)(benchmark::State&))
|
101
|
+
: name_(name),
|
102
|
+
func_([func](int iters, int arg) {
|
103
|
+
benchmark::State state(iters);
|
104
|
+
func(state);
|
105
|
+
}),
|
106
|
+
lo_(0),
|
107
|
+
hi_(0),
|
108
|
+
has_arg_(false) {
|
109
|
+
Register();
|
110
|
+
}
|
111
|
+
|
112
|
+
Benchmark(const char* name, void (*func)(benchmark::State&), int lo, int hi)
|
113
|
+
: name_(name),
|
114
|
+
func_([func](int iters, int arg) {
|
115
|
+
benchmark::State state(iters, arg);
|
116
|
+
func(state);
|
117
|
+
}),
|
118
|
+
lo_(lo),
|
119
|
+
hi_(hi),
|
120
|
+
has_arg_(true) {
|
121
|
+
Register();
|
122
|
+
}
|
123
|
+
|
124
|
+
// Pretend to support multiple threads.
|
125
|
+
Benchmark* ThreadRange(int lo, int hi) { return this; }
|
126
|
+
|
127
|
+
const char* name() const { return name_; }
|
128
|
+
const std::function<void(int, int)>& func() const { return func_; }
|
129
|
+
int lo() const { return lo_; }
|
130
|
+
int hi() const { return hi_; }
|
131
|
+
bool has_arg() const { return has_arg_; }
|
132
|
+
|
133
|
+
private:
|
134
|
+
void Register();
|
135
|
+
|
136
|
+
const char* name_;
|
137
|
+
std::function<void(int, int)> func_;
|
138
|
+
int lo_;
|
139
|
+
int hi_;
|
140
|
+
bool has_arg_;
|
141
|
+
|
142
|
+
Benchmark(const Benchmark&) = delete;
|
143
|
+
Benchmark& operator=(const Benchmark&) = delete;
|
144
|
+
};
|
145
|
+
|
146
|
+
} // namespace testing
|
147
|
+
|
148
|
+
#define BENCHMARK(f) \
|
149
|
+
::testing::Benchmark* _benchmark_##f = \
|
150
|
+
(new ::testing::Benchmark(#f, f))
|
151
|
+
|
152
|
+
#define BENCHMARK_RANGE(f, lo, hi) \
|
153
|
+
::testing::Benchmark* _benchmark_##f = \
|
154
|
+
(new ::testing::Benchmark(#f, f, lo, hi))
|
155
|
+
|
156
|
+
#endif // UTIL_BENCHMARK_H_
|