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,392 @@
|
|
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_SPARSE_ARRAY_H_
|
6
|
+
#define RE2_SPARSE_ARRAY_H_
|
7
|
+
|
8
|
+
// DESCRIPTION
|
9
|
+
//
|
10
|
+
// SparseArray<T>(m) is a map from integers in [0, m) to T values.
|
11
|
+
// It requires (sizeof(T)+sizeof(int))*m memory, but it provides
|
12
|
+
// fast iteration through the elements in the array and fast clearing
|
13
|
+
// of the array. The array has a concept of certain elements being
|
14
|
+
// uninitialized (having no value).
|
15
|
+
//
|
16
|
+
// Insertion and deletion are constant time operations.
|
17
|
+
//
|
18
|
+
// Allocating the array is a constant time operation
|
19
|
+
// when memory allocation is a constant time operation.
|
20
|
+
//
|
21
|
+
// Clearing the array is a constant time operation (unusual!).
|
22
|
+
//
|
23
|
+
// Iterating through the array is an O(n) operation, where n
|
24
|
+
// is the number of items in the array (not O(m)).
|
25
|
+
//
|
26
|
+
// The array iterator visits entries in the order they were first
|
27
|
+
// inserted into the array. It is safe to add items to the array while
|
28
|
+
// using an iterator: the iterator will visit indices added to the array
|
29
|
+
// during the iteration, but will not re-visit indices whose values
|
30
|
+
// change after visiting. Thus SparseArray can be a convenient
|
31
|
+
// implementation of a work queue.
|
32
|
+
//
|
33
|
+
// The SparseArray implementation is NOT thread-safe. It is up to the
|
34
|
+
// caller to make sure only one thread is accessing the array. (Typically
|
35
|
+
// these arrays are temporary values and used in situations where speed is
|
36
|
+
// important.)
|
37
|
+
//
|
38
|
+
// The SparseArray interface does not present all the usual STL bells and
|
39
|
+
// whistles.
|
40
|
+
//
|
41
|
+
// Implemented with reference to Briggs & Torczon, An Efficient
|
42
|
+
// Representation for Sparse Sets, ACM Letters on Programming Languages
|
43
|
+
// and Systems, Volume 2, Issue 1-4 (March-Dec. 1993), pp. 59-69.
|
44
|
+
//
|
45
|
+
// Briggs & Torczon popularized this technique, but it had been known
|
46
|
+
// long before their paper. They point out that Aho, Hopcroft, and
|
47
|
+
// Ullman's 1974 Design and Analysis of Computer Algorithms and Bentley's
|
48
|
+
// 1986 Programming Pearls both hint at the technique in exercises to the
|
49
|
+
// reader (in Aho & Hopcroft, exercise 2.12; in Bentley, column 1
|
50
|
+
// exercise 8).
|
51
|
+
//
|
52
|
+
// Briggs & Torczon describe a sparse set implementation. I have
|
53
|
+
// trivially generalized it to create a sparse array (actually the original
|
54
|
+
// target of the AHU and Bentley exercises).
|
55
|
+
|
56
|
+
// IMPLEMENTATION
|
57
|
+
//
|
58
|
+
// SparseArray is an array dense_ and an array sparse_ of identical size.
|
59
|
+
// At any point, the number of elements in the sparse array is size_.
|
60
|
+
//
|
61
|
+
// The array dense_ contains the size_ elements in the sparse array (with
|
62
|
+
// their indices),
|
63
|
+
// in the order that the elements were first inserted. This array is dense:
|
64
|
+
// the size_ pairs are dense_[0] through dense_[size_-1].
|
65
|
+
//
|
66
|
+
// The array sparse_ maps from indices in [0,m) to indices in [0,size_).
|
67
|
+
// For indices present in the array, dense_[sparse_[i]].index_ == i.
|
68
|
+
// For indices not present in the array, sparse_ can contain any value at all,
|
69
|
+
// perhaps outside the range [0, size_) but perhaps not.
|
70
|
+
//
|
71
|
+
// The lax requirement on sparse_ values makes clearing the array very easy:
|
72
|
+
// set size_ to 0. Lookups are slightly more complicated.
|
73
|
+
// An index i has a value in the array if and only if:
|
74
|
+
// sparse_[i] is in [0, size_) AND
|
75
|
+
// dense_[sparse_[i]].index_ == i.
|
76
|
+
// If both these properties hold, only then it is safe to refer to
|
77
|
+
// dense_[sparse_[i]].value_
|
78
|
+
// as the value associated with index i.
|
79
|
+
//
|
80
|
+
// To insert a new entry, set sparse_[i] to size_,
|
81
|
+
// initialize dense_[size_], and then increment size_.
|
82
|
+
//
|
83
|
+
// To make the sparse array as efficient as possible for non-primitive types,
|
84
|
+
// elements may or may not be destroyed when they are deleted from the sparse
|
85
|
+
// array through a call to resize(). They immediately become inaccessible, but
|
86
|
+
// they are only guaranteed to be destroyed when the SparseArray destructor is
|
87
|
+
// called.
|
88
|
+
//
|
89
|
+
// A moved-from SparseArray will be empty.
|
90
|
+
|
91
|
+
// Doing this simplifies the logic below.
|
92
|
+
#ifndef __has_feature
|
93
|
+
#define __has_feature(x) 0
|
94
|
+
#endif
|
95
|
+
|
96
|
+
#include <assert.h>
|
97
|
+
#include <stdint.h>
|
98
|
+
#if __has_feature(memory_sanitizer)
|
99
|
+
#include <sanitizer/msan_interface.h>
|
100
|
+
#endif
|
101
|
+
#include <algorithm>
|
102
|
+
#include <memory>
|
103
|
+
#include <utility>
|
104
|
+
|
105
|
+
#include "re2/pod_array.h"
|
106
|
+
|
107
|
+
namespace re2 {
|
108
|
+
|
109
|
+
template<typename Value>
|
110
|
+
class SparseArray {
|
111
|
+
public:
|
112
|
+
SparseArray();
|
113
|
+
explicit SparseArray(int max_size);
|
114
|
+
~SparseArray();
|
115
|
+
|
116
|
+
// IndexValue pairs: exposed in SparseArray::iterator.
|
117
|
+
class IndexValue;
|
118
|
+
|
119
|
+
typedef IndexValue* iterator;
|
120
|
+
typedef const IndexValue* const_iterator;
|
121
|
+
|
122
|
+
SparseArray(const SparseArray& src);
|
123
|
+
SparseArray(SparseArray&& src);
|
124
|
+
|
125
|
+
SparseArray& operator=(const SparseArray& src);
|
126
|
+
SparseArray& operator=(SparseArray&& src);
|
127
|
+
|
128
|
+
// Return the number of entries in the array.
|
129
|
+
int size() const {
|
130
|
+
return size_;
|
131
|
+
}
|
132
|
+
|
133
|
+
// Indicate whether the array is empty.
|
134
|
+
int empty() const {
|
135
|
+
return size_ == 0;
|
136
|
+
}
|
137
|
+
|
138
|
+
// Iterate over the array.
|
139
|
+
iterator begin() {
|
140
|
+
return dense_.data();
|
141
|
+
}
|
142
|
+
iterator end() {
|
143
|
+
return dense_.data() + size_;
|
144
|
+
}
|
145
|
+
|
146
|
+
const_iterator begin() const {
|
147
|
+
return dense_.data();
|
148
|
+
}
|
149
|
+
const_iterator end() const {
|
150
|
+
return dense_.data() + size_;
|
151
|
+
}
|
152
|
+
|
153
|
+
// Change the maximum size of the array.
|
154
|
+
// Invalidates all iterators.
|
155
|
+
void resize(int new_max_size);
|
156
|
+
|
157
|
+
// Return the maximum size of the array.
|
158
|
+
// Indices can be in the range [0, max_size).
|
159
|
+
int max_size() const {
|
160
|
+
if (dense_.data() != NULL)
|
161
|
+
return dense_.size();
|
162
|
+
else
|
163
|
+
return 0;
|
164
|
+
}
|
165
|
+
|
166
|
+
// Clear the array.
|
167
|
+
void clear() {
|
168
|
+
size_ = 0;
|
169
|
+
}
|
170
|
+
|
171
|
+
// Check whether index i is in the array.
|
172
|
+
bool has_index(int i) const;
|
173
|
+
|
174
|
+
// Comparison function for sorting.
|
175
|
+
// Can sort the sparse array so that future iterations
|
176
|
+
// will visit indices in increasing order using
|
177
|
+
// std::sort(arr.begin(), arr.end(), arr.less);
|
178
|
+
static bool less(const IndexValue& a, const IndexValue& b);
|
179
|
+
|
180
|
+
public:
|
181
|
+
// Set the value at index i to v.
|
182
|
+
iterator set(int i, const Value& v) {
|
183
|
+
return SetInternal(true, i, v);
|
184
|
+
}
|
185
|
+
|
186
|
+
// Set the value at new index i to v.
|
187
|
+
// Fast but unsafe: only use if has_index(i) is false.
|
188
|
+
iterator set_new(int i, const Value& v) {
|
189
|
+
return SetInternal(false, i, v);
|
190
|
+
}
|
191
|
+
|
192
|
+
// Set the value at index i to v.
|
193
|
+
// Fast but unsafe: only use if has_index(i) is true.
|
194
|
+
iterator set_existing(int i, const Value& v) {
|
195
|
+
return SetExistingInternal(i, v);
|
196
|
+
}
|
197
|
+
|
198
|
+
// Get the value at index i.
|
199
|
+
// Fast but unsafe: only use if has_index(i) is true.
|
200
|
+
Value& get_existing(int i) {
|
201
|
+
assert(has_index(i));
|
202
|
+
return dense_[sparse_[i]].value_;
|
203
|
+
}
|
204
|
+
const Value& get_existing(int i) const {
|
205
|
+
assert(has_index(i));
|
206
|
+
return dense_[sparse_[i]].value_;
|
207
|
+
}
|
208
|
+
|
209
|
+
private:
|
210
|
+
iterator SetInternal(bool allow_existing, int i, const Value& v) {
|
211
|
+
DebugCheckInvariants();
|
212
|
+
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
213
|
+
assert(false && "illegal index");
|
214
|
+
// Semantically, end() would be better here, but we already know
|
215
|
+
// the user did something stupid, so begin() insulates them from
|
216
|
+
// dereferencing an invalid pointer.
|
217
|
+
return begin();
|
218
|
+
}
|
219
|
+
if (!allow_existing) {
|
220
|
+
assert(!has_index(i));
|
221
|
+
create_index(i);
|
222
|
+
} else {
|
223
|
+
if (!has_index(i))
|
224
|
+
create_index(i);
|
225
|
+
}
|
226
|
+
return SetExistingInternal(i, v);
|
227
|
+
}
|
228
|
+
|
229
|
+
iterator SetExistingInternal(int i, const Value& v) {
|
230
|
+
DebugCheckInvariants();
|
231
|
+
assert(has_index(i));
|
232
|
+
dense_[sparse_[i]].value_ = v;
|
233
|
+
DebugCheckInvariants();
|
234
|
+
return dense_.data() + sparse_[i];
|
235
|
+
}
|
236
|
+
|
237
|
+
// Add the index i to the array.
|
238
|
+
// Only use if has_index(i) is known to be false.
|
239
|
+
// Since it doesn't set the value associated with i,
|
240
|
+
// this function is private, only intended as a helper
|
241
|
+
// for other methods.
|
242
|
+
void create_index(int i);
|
243
|
+
|
244
|
+
// In debug mode, verify that some invariant properties of the class
|
245
|
+
// are being maintained. This is called at the end of the constructor
|
246
|
+
// and at the beginning and end of all public non-const member functions.
|
247
|
+
void DebugCheckInvariants() const;
|
248
|
+
|
249
|
+
// Initializes memory for elements [min, max).
|
250
|
+
void MaybeInitializeMemory(int min, int max) {
|
251
|
+
#if __has_feature(memory_sanitizer)
|
252
|
+
__msan_unpoison(sparse_.data() + min, (max - min) * sizeof sparse_[0]);
|
253
|
+
#elif defined(RE2_ON_VALGRIND)
|
254
|
+
for (int i = min; i < max; i++) {
|
255
|
+
sparse_[i] = 0xababababU;
|
256
|
+
}
|
257
|
+
#endif
|
258
|
+
}
|
259
|
+
|
260
|
+
int size_ = 0;
|
261
|
+
PODArray<int> sparse_;
|
262
|
+
PODArray<IndexValue> dense_;
|
263
|
+
};
|
264
|
+
|
265
|
+
template<typename Value>
|
266
|
+
SparseArray<Value>::SparseArray() = default;
|
267
|
+
|
268
|
+
template<typename Value>
|
269
|
+
SparseArray<Value>::SparseArray(const SparseArray& src)
|
270
|
+
: size_(src.size_),
|
271
|
+
sparse_(src.max_size()),
|
272
|
+
dense_(src.max_size()) {
|
273
|
+
std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
|
274
|
+
std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
|
275
|
+
}
|
276
|
+
|
277
|
+
template<typename Value>
|
278
|
+
SparseArray<Value>::SparseArray(SparseArray&& src)
|
279
|
+
: size_(src.size_),
|
280
|
+
sparse_(std::move(src.sparse_)),
|
281
|
+
dense_(std::move(src.dense_)) {
|
282
|
+
src.size_ = 0;
|
283
|
+
}
|
284
|
+
|
285
|
+
template<typename Value>
|
286
|
+
SparseArray<Value>& SparseArray<Value>::operator=(const SparseArray& src) {
|
287
|
+
// Construct these first for exception safety.
|
288
|
+
PODArray<int> a(src.max_size());
|
289
|
+
PODArray<IndexValue> b(src.max_size());
|
290
|
+
|
291
|
+
size_ = src.size_;
|
292
|
+
sparse_ = std::move(a);
|
293
|
+
dense_ = std::move(b);
|
294
|
+
std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
|
295
|
+
std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
|
296
|
+
return *this;
|
297
|
+
}
|
298
|
+
|
299
|
+
template<typename Value>
|
300
|
+
SparseArray<Value>& SparseArray<Value>::operator=(SparseArray&& src) {
|
301
|
+
size_ = src.size_;
|
302
|
+
sparse_ = std::move(src.sparse_);
|
303
|
+
dense_ = std::move(src.dense_);
|
304
|
+
src.size_ = 0;
|
305
|
+
return *this;
|
306
|
+
}
|
307
|
+
|
308
|
+
// IndexValue pairs: exposed in SparseArray::iterator.
|
309
|
+
template<typename Value>
|
310
|
+
class SparseArray<Value>::IndexValue {
|
311
|
+
public:
|
312
|
+
int index() const { return index_; }
|
313
|
+
Value& value() { return value_; }
|
314
|
+
const Value& value() const { return value_; }
|
315
|
+
|
316
|
+
private:
|
317
|
+
friend class SparseArray;
|
318
|
+
int index_;
|
319
|
+
Value value_;
|
320
|
+
};
|
321
|
+
|
322
|
+
// Change the maximum size of the array.
|
323
|
+
// Invalidates all iterators.
|
324
|
+
template<typename Value>
|
325
|
+
void SparseArray<Value>::resize(int new_max_size) {
|
326
|
+
DebugCheckInvariants();
|
327
|
+
if (new_max_size > max_size()) {
|
328
|
+
const int old_max_size = max_size();
|
329
|
+
|
330
|
+
// Construct these first for exception safety.
|
331
|
+
PODArray<int> a(new_max_size);
|
332
|
+
PODArray<IndexValue> b(new_max_size);
|
333
|
+
|
334
|
+
std::copy_n(sparse_.data(), old_max_size, a.data());
|
335
|
+
std::copy_n(dense_.data(), old_max_size, b.data());
|
336
|
+
|
337
|
+
sparse_ = std::move(a);
|
338
|
+
dense_ = std::move(b);
|
339
|
+
|
340
|
+
MaybeInitializeMemory(old_max_size, new_max_size);
|
341
|
+
}
|
342
|
+
if (size_ > new_max_size)
|
343
|
+
size_ = new_max_size;
|
344
|
+
DebugCheckInvariants();
|
345
|
+
}
|
346
|
+
|
347
|
+
// Check whether index i is in the array.
|
348
|
+
template<typename Value>
|
349
|
+
bool SparseArray<Value>::has_index(int i) const {
|
350
|
+
assert(i >= 0);
|
351
|
+
assert(i < max_size());
|
352
|
+
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
353
|
+
return false;
|
354
|
+
}
|
355
|
+
// Unsigned comparison avoids checking sparse_[i] < 0.
|
356
|
+
return (uint32_t)sparse_[i] < (uint32_t)size_ &&
|
357
|
+
dense_[sparse_[i]].index_ == i;
|
358
|
+
}
|
359
|
+
|
360
|
+
template<typename Value>
|
361
|
+
void SparseArray<Value>::create_index(int i) {
|
362
|
+
assert(!has_index(i));
|
363
|
+
assert(size_ < max_size());
|
364
|
+
sparse_[i] = size_;
|
365
|
+
dense_[size_].index_ = i;
|
366
|
+
size_++;
|
367
|
+
}
|
368
|
+
|
369
|
+
template<typename Value> SparseArray<Value>::SparseArray(int max_size) :
|
370
|
+
sparse_(max_size), dense_(max_size) {
|
371
|
+
MaybeInitializeMemory(size_, max_size);
|
372
|
+
DebugCheckInvariants();
|
373
|
+
}
|
374
|
+
|
375
|
+
template<typename Value> SparseArray<Value>::~SparseArray() {
|
376
|
+
DebugCheckInvariants();
|
377
|
+
}
|
378
|
+
|
379
|
+
template<typename Value> void SparseArray<Value>::DebugCheckInvariants() const {
|
380
|
+
assert(0 <= size_);
|
381
|
+
assert(size_ <= max_size());
|
382
|
+
}
|
383
|
+
|
384
|
+
// Comparison function for sorting.
|
385
|
+
template<typename Value> bool SparseArray<Value>::less(const IndexValue& a,
|
386
|
+
const IndexValue& b) {
|
387
|
+
return a.index_ < b.index_;
|
388
|
+
}
|
389
|
+
|
390
|
+
} // namespace re2
|
391
|
+
|
392
|
+
#endif // RE2_SPARSE_ARRAY_H_
|
@@ -0,0 +1,264 @@
|
|
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_SPARSE_SET_H_
|
6
|
+
#define RE2_SPARSE_SET_H_
|
7
|
+
|
8
|
+
// DESCRIPTION
|
9
|
+
//
|
10
|
+
// SparseSet(m) is a set of integers in [0, m).
|
11
|
+
// It requires sizeof(int)*m memory, but it provides
|
12
|
+
// fast iteration through the elements in the set and fast clearing
|
13
|
+
// of the set.
|
14
|
+
//
|
15
|
+
// Insertion and deletion are constant time operations.
|
16
|
+
//
|
17
|
+
// Allocating the set is a constant time operation
|
18
|
+
// when memory allocation is a constant time operation.
|
19
|
+
//
|
20
|
+
// Clearing the set is a constant time operation (unusual!).
|
21
|
+
//
|
22
|
+
// Iterating through the set is an O(n) operation, where n
|
23
|
+
// is the number of items in the set (not O(m)).
|
24
|
+
//
|
25
|
+
// The set iterator visits entries in the order they were first
|
26
|
+
// inserted into the set. It is safe to add items to the set while
|
27
|
+
// using an iterator: the iterator will visit indices added to the set
|
28
|
+
// during the iteration, but will not re-visit indices whose values
|
29
|
+
// change after visiting. Thus SparseSet can be a convenient
|
30
|
+
// implementation of a work queue.
|
31
|
+
//
|
32
|
+
// The SparseSet implementation is NOT thread-safe. It is up to the
|
33
|
+
// caller to make sure only one thread is accessing the set. (Typically
|
34
|
+
// these sets are temporary values and used in situations where speed is
|
35
|
+
// important.)
|
36
|
+
//
|
37
|
+
// The SparseSet interface does not present all the usual STL bells and
|
38
|
+
// whistles.
|
39
|
+
//
|
40
|
+
// Implemented with reference to Briggs & Torczon, An Efficient
|
41
|
+
// Representation for Sparse Sets, ACM Letters on Programming Languages
|
42
|
+
// and Systems, Volume 2, Issue 1-4 (March-Dec. 1993), pp. 59-69.
|
43
|
+
//
|
44
|
+
// This is a specialization of sparse array; see sparse_array.h.
|
45
|
+
|
46
|
+
// IMPLEMENTATION
|
47
|
+
//
|
48
|
+
// See sparse_array.h for implementation details.
|
49
|
+
|
50
|
+
// Doing this simplifies the logic below.
|
51
|
+
#ifndef __has_feature
|
52
|
+
#define __has_feature(x) 0
|
53
|
+
#endif
|
54
|
+
|
55
|
+
#include <assert.h>
|
56
|
+
#include <stdint.h>
|
57
|
+
#if __has_feature(memory_sanitizer)
|
58
|
+
#include <sanitizer/msan_interface.h>
|
59
|
+
#endif
|
60
|
+
#include <algorithm>
|
61
|
+
#include <memory>
|
62
|
+
#include <utility>
|
63
|
+
|
64
|
+
#include "re2/pod_array.h"
|
65
|
+
|
66
|
+
namespace re2 {
|
67
|
+
|
68
|
+
template<typename Value>
|
69
|
+
class SparseSetT {
|
70
|
+
public:
|
71
|
+
SparseSetT();
|
72
|
+
explicit SparseSetT(int max_size);
|
73
|
+
~SparseSetT();
|
74
|
+
|
75
|
+
typedef int* iterator;
|
76
|
+
typedef const int* const_iterator;
|
77
|
+
|
78
|
+
// Return the number of entries in the set.
|
79
|
+
int size() const {
|
80
|
+
return size_;
|
81
|
+
}
|
82
|
+
|
83
|
+
// Indicate whether the set is empty.
|
84
|
+
int empty() const {
|
85
|
+
return size_ == 0;
|
86
|
+
}
|
87
|
+
|
88
|
+
// Iterate over the set.
|
89
|
+
iterator begin() {
|
90
|
+
return dense_.data();
|
91
|
+
}
|
92
|
+
iterator end() {
|
93
|
+
return dense_.data() + size_;
|
94
|
+
}
|
95
|
+
|
96
|
+
const_iterator begin() const {
|
97
|
+
return dense_.data();
|
98
|
+
}
|
99
|
+
const_iterator end() const {
|
100
|
+
return dense_.data() + size_;
|
101
|
+
}
|
102
|
+
|
103
|
+
// Change the maximum size of the set.
|
104
|
+
// Invalidates all iterators.
|
105
|
+
void resize(int new_max_size);
|
106
|
+
|
107
|
+
// Return the maximum size of the set.
|
108
|
+
// Indices can be in the range [0, max_size).
|
109
|
+
int max_size() const {
|
110
|
+
if (dense_.data() != NULL)
|
111
|
+
return dense_.size();
|
112
|
+
else
|
113
|
+
return 0;
|
114
|
+
}
|
115
|
+
|
116
|
+
// Clear the set.
|
117
|
+
void clear() {
|
118
|
+
size_ = 0;
|
119
|
+
}
|
120
|
+
|
121
|
+
// Check whether index i is in the set.
|
122
|
+
bool contains(int i) const;
|
123
|
+
|
124
|
+
// Comparison function for sorting.
|
125
|
+
// Can sort the sparse set so that future iterations
|
126
|
+
// will visit indices in increasing order using
|
127
|
+
// std::sort(arr.begin(), arr.end(), arr.less);
|
128
|
+
static bool less(int a, int b);
|
129
|
+
|
130
|
+
public:
|
131
|
+
// Insert index i into the set.
|
132
|
+
iterator insert(int i) {
|
133
|
+
return InsertInternal(true, i);
|
134
|
+
}
|
135
|
+
|
136
|
+
// Insert index i into the set.
|
137
|
+
// Fast but unsafe: only use if contains(i) is false.
|
138
|
+
iterator insert_new(int i) {
|
139
|
+
return InsertInternal(false, i);
|
140
|
+
}
|
141
|
+
|
142
|
+
private:
|
143
|
+
iterator InsertInternal(bool allow_existing, int i) {
|
144
|
+
DebugCheckInvariants();
|
145
|
+
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
146
|
+
assert(false && "illegal index");
|
147
|
+
// Semantically, end() would be better here, but we already know
|
148
|
+
// the user did something stupid, so begin() insulates them from
|
149
|
+
// dereferencing an invalid pointer.
|
150
|
+
return begin();
|
151
|
+
}
|
152
|
+
if (!allow_existing) {
|
153
|
+
assert(!contains(i));
|
154
|
+
create_index(i);
|
155
|
+
} else {
|
156
|
+
if (!contains(i))
|
157
|
+
create_index(i);
|
158
|
+
}
|
159
|
+
DebugCheckInvariants();
|
160
|
+
return dense_.data() + sparse_[i];
|
161
|
+
}
|
162
|
+
|
163
|
+
// Add the index i to the set.
|
164
|
+
// Only use if contains(i) is known to be false.
|
165
|
+
// This function is private, only intended as a helper
|
166
|
+
// for other methods.
|
167
|
+
void create_index(int i);
|
168
|
+
|
169
|
+
// In debug mode, verify that some invariant properties of the class
|
170
|
+
// are being maintained. This is called at the end of the constructor
|
171
|
+
// and at the beginning and end of all public non-const member functions.
|
172
|
+
void DebugCheckInvariants() const;
|
173
|
+
|
174
|
+
// Initializes memory for elements [min, max).
|
175
|
+
void MaybeInitializeMemory(int min, int max) {
|
176
|
+
#if __has_feature(memory_sanitizer)
|
177
|
+
__msan_unpoison(sparse_.data() + min, (max - min) * sizeof sparse_[0]);
|
178
|
+
#elif defined(RE2_ON_VALGRIND)
|
179
|
+
for (int i = min; i < max; i++) {
|
180
|
+
sparse_[i] = 0xababababU;
|
181
|
+
}
|
182
|
+
#endif
|
183
|
+
}
|
184
|
+
|
185
|
+
int size_ = 0;
|
186
|
+
PODArray<int> sparse_;
|
187
|
+
PODArray<int> dense_;
|
188
|
+
};
|
189
|
+
|
190
|
+
template<typename Value>
|
191
|
+
SparseSetT<Value>::SparseSetT() = default;
|
192
|
+
|
193
|
+
// Change the maximum size of the set.
|
194
|
+
// Invalidates all iterators.
|
195
|
+
template<typename Value>
|
196
|
+
void SparseSetT<Value>::resize(int new_max_size) {
|
197
|
+
DebugCheckInvariants();
|
198
|
+
if (new_max_size > max_size()) {
|
199
|
+
const int old_max_size = max_size();
|
200
|
+
|
201
|
+
// Construct these first for exception safety.
|
202
|
+
PODArray<int> a(new_max_size);
|
203
|
+
PODArray<int> b(new_max_size);
|
204
|
+
|
205
|
+
std::copy_n(sparse_.data(), old_max_size, a.data());
|
206
|
+
std::copy_n(dense_.data(), old_max_size, b.data());
|
207
|
+
|
208
|
+
sparse_ = std::move(a);
|
209
|
+
dense_ = std::move(b);
|
210
|
+
|
211
|
+
MaybeInitializeMemory(old_max_size, new_max_size);
|
212
|
+
}
|
213
|
+
if (size_ > new_max_size)
|
214
|
+
size_ = new_max_size;
|
215
|
+
DebugCheckInvariants();
|
216
|
+
}
|
217
|
+
|
218
|
+
// Check whether index i is in the set.
|
219
|
+
template<typename Value>
|
220
|
+
bool SparseSetT<Value>::contains(int i) const {
|
221
|
+
assert(i >= 0);
|
222
|
+
assert(i < max_size());
|
223
|
+
if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
|
224
|
+
return false;
|
225
|
+
}
|
226
|
+
// Unsigned comparison avoids checking sparse_[i] < 0.
|
227
|
+
return (uint32_t)sparse_[i] < (uint32_t)size_ &&
|
228
|
+
dense_[sparse_[i]] == i;
|
229
|
+
}
|
230
|
+
|
231
|
+
template<typename Value>
|
232
|
+
void SparseSetT<Value>::create_index(int i) {
|
233
|
+
assert(!contains(i));
|
234
|
+
assert(size_ < max_size());
|
235
|
+
sparse_[i] = size_;
|
236
|
+
dense_[size_] = i;
|
237
|
+
size_++;
|
238
|
+
}
|
239
|
+
|
240
|
+
template<typename Value> SparseSetT<Value>::SparseSetT(int max_size) :
|
241
|
+
sparse_(max_size), dense_(max_size) {
|
242
|
+
MaybeInitializeMemory(size_, max_size);
|
243
|
+
DebugCheckInvariants();
|
244
|
+
}
|
245
|
+
|
246
|
+
template<typename Value> SparseSetT<Value>::~SparseSetT() {
|
247
|
+
DebugCheckInvariants();
|
248
|
+
}
|
249
|
+
|
250
|
+
template<typename Value> void SparseSetT<Value>::DebugCheckInvariants() const {
|
251
|
+
assert(0 <= size_);
|
252
|
+
assert(size_ <= max_size());
|
253
|
+
}
|
254
|
+
|
255
|
+
// Comparison function for sorting.
|
256
|
+
template<typename Value> bool SparseSetT<Value>::less(int a, int b) {
|
257
|
+
return a < b;
|
258
|
+
}
|
259
|
+
|
260
|
+
typedef SparseSetT<void> SparseSet;
|
261
|
+
|
262
|
+
} // namespace re2
|
263
|
+
|
264
|
+
#endif // RE2_SPARSE_SET_H_
|