Coverage Report

Created: 2024-11-18 11:49

/root/doris/be/src/gutil/stl_util.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2002 Google Inc.
2
//
3
// Licensed to the Apache Software Foundation (ASF) under one
4
// or more contributor license agreements.  See the NOTICE file
5
// distributed with this work for additional information
6
// regarding copyright ownership.  The ASF licenses this file
7
// to you under the Apache License, Version 2.0 (the
8
// "License"); you may not use this file except in compliance
9
// with the License.  You may obtain a copy of the License at
10
//
11
//   http://www.apache.org/licenses/LICENSE-2.0
12
//
13
// Unless required by applicable law or agreed to in writing,
14
// software distributed under the License is distributed on an
15
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
// KIND, either express or implied.  See the License for the
17
// specific language governing permissions and limitations
18
// under the License.
19
//
20
// ---
21
//
22
//
23
// STL utility functions.  Usually, these replace built-in, but slow(!),
24
// STL functions with more efficient versions or provide a more convenient
25
// and Google friendly API.
26
//
27
28
#pragma once
29
30
#include <stddef.h>
31
#include <string.h> // for memcpy
32
33
#include <algorithm>
34
using std::copy;
35
using std::max;
36
using std::min;
37
using std::reverse;
38
using std::sort;
39
using std::swap;
40
#include <cassert>
41
#include <deque>
42
using std::deque;
43
#include <functional>
44
using std::less;
45
#include <iterator>
46
using std::back_insert_iterator;
47
using std::iterator_traits;
48
#include <memory>
49
#include <string>
50
using std::string;
51
#include <vector>
52
using std::vector;
53
54
#include "gutil/integral_types.h"
55
#include "gutil/macros.h"
56
#include "gutil/port.h"
57
58
// Sort and remove duplicates of an STL vector or deque.
59
template <class T>
60
void STLSortAndRemoveDuplicates(T* v) {
61
    sort(v->begin(), v->end());
62
    v->erase(unique(v->begin(), v->end()), v->end());
63
}
64
65
// Clear internal memory of an STL object.
66
// STL clear()/reserve(0) does not always free internal memory allocated
67
// This function uses swap/destructor to ensure the internal memory is freed.
68
template <class T>
69
void STLClearObject(T* obj) {
70
    T tmp;
71
    tmp.swap(*obj);
72
    obj->reserve(0); // this is because sometimes "T tmp" allocates objects with
73
                     // memory (arena implementation?).  use reserve()
74
                     // to clear() even if it doesn't always work
75
}
76
77
// Specialization for deque. Same as STLClearObject but doesn't call reserve
78
// since deque doesn't have reserve.
79
template <class T, class A>
80
void STLClearObject(deque<T, A>* obj) {
81
    deque<T, A> tmp;
82
    tmp.swap(*obj);
83
}
84
85
// Reduce memory usage on behalf of object if its capacity is greater
86
// than or equal to "limit", which defaults to 2^20.
87
template <class T>
88
 void STLClearIfBig(T* obj, size_t limit = 1 << 20) {
89
    if (obj->capacity() >= limit) {
90
        STLClearObject(obj);
91
    } else {
92
        obj->clear();
93
    }
94
}
95
96
// Specialization for deque, which doesn't implement capacity().
97
template <class T, class A>
98
 void STLClearIfBig(deque<T, A>* obj, size_t limit = 1 << 20) {
99
    if (obj->size() >= limit) {
100
        STLClearObject(obj);
101
    } else {
102
        obj->clear();
103
    }
104
}
105
106
// Reduce the number of buckets in a hash_set or hash_map back to the
107
// default if the current number of buckets is "limit" or more.
108
//
109
// Suppose you repeatedly fill and clear a hash_map or hash_set.  If
110
// you ever insert a lot of items, then your hash table will have lots
111
// of buckets thereafter.  (The number of buckets is not reduced when
112
// the table is cleared.)  Having lots of buckets is good if you
113
// insert comparably many items in every iteration, because you'll
114
// reduce collisions and table resizes.  But having lots of buckets is
115
// bad if you insert few items in most subsequent iterations, because
116
// repeatedly clearing out all those buckets can get expensive.
117
//
118
// One solution is to call STLClearHashIfBig() with a "limit" value
119
// that is a small multiple of the typical number of items in your
120
// table.  In the common case, this is equivalent to an ordinary
121
// clear.  In the rare case where you insert a lot of items, the
122
// number of buckets is reset to the default to keep subsequent clear
123
// operations cheap.  Note that the default number of buckets is 193
124
// in the Gnu library implementation as of Jan '08.
125
template <class T>
126
 void STLClearHashIfBig(T* obj, size_t limit) {
127
    if (obj->bucket_count() >= limit) {
128
        T tmp;
129
        tmp.swap(*obj);
130
    } else {
131
        obj->clear();
132
    }
133
}
134
135
// Reserve space for STL object.
136
// STL's reserve() will always copy.
137
// This function avoid the copy if we already have capacity
138
template <class T>
139
void STLReserveIfNeeded(T* obj, int new_size) {
140
    if (obj->capacity() < new_size) // increase capacity
141
        obj->reserve(new_size);
142
    else if (obj->size() > new_size) // reduce size
143
        obj->resize(new_size);
144
}
145
146
// STLDeleteContainerPointers()
147
//  For a range within a container of pointers, calls delete
148
//  (non-array version) on these pointers.
149
// NOTE: for these three functions, we could just implement a DeleteObject
150
// functor and then call for_each() on the range and functor, but this
151
// requires us to pull in all of <algorithm>, which seems expensive.
152
// For hash_[multi]set, it is important that this deletes behind the iterator
153
// because the hash_set may call the hash function on the iterator when it is
154
// advanced, which could result in the hash function trying to deference a
155
// stale pointer.
156
// NOTE: If you're calling this on an entire container, you probably want
157
// to call STLDeleteElements(&container) instead, or use an ElementDeleter.
158
template <class ForwardIterator>
159
void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) {
160
    while (begin != end) {
161
        ForwardIterator temp = begin;
162
        ++begin;
163
        delete *temp;
164
    }
165
}
166
167
// STLDeleteContainerPairPointers()
168
//  For a range within a container of pairs, calls delete
169
//  (non-array version) on BOTH items in the pairs.
170
// NOTE: Like STLDeleteContainerPointers, it is important that this deletes
171
// behind the iterator because if both the key and value are deleted, the
172
// container may call the hash function on the iterator when it is advanced,
173
// which could result in the hash function trying to dereference a stale
174
// pointer.
175
template <class ForwardIterator>
176
void STLDeleteContainerPairPointers(ForwardIterator begin, ForwardIterator end) {
177
    while (begin != end) {
178
        ForwardIterator temp = begin;
179
        ++begin;
180
        delete temp->first;
181
        delete temp->second;
182
    }
183
}
184
185
// STLDeleteContainerPairFirstPointers()
186
//  For a range within a container of pairs, calls delete (non-array version)
187
//  on the FIRST item in the pairs.
188
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
189
template <class ForwardIterator>
190
void STLDeleteContainerPairFirstPointers(ForwardIterator begin, ForwardIterator end) {
191
    while (begin != end) {
192
        ForwardIterator temp = begin;
193
        ++begin;
194
        delete temp->first;
195
    }
196
}
197
198
// STLDeleteContainerPairSecondPointers()
199
//  For a range within a container of pairs, calls delete
200
//  (non-array version) on the SECOND item in the pairs.
201
// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
202
// Deleting the value does not always invalidate the iterator, but it may
203
// do so if the key is a pointer into the value object.
204
// NOTE: If you're calling this on an entire container, you probably want
205
// to call STLDeleteValues(&container) instead, or use ValueDeleter.
206
template <class ForwardIterator>
207
1
void STLDeleteContainerPairSecondPointers(ForwardIterator begin, ForwardIterator end) {
208
10
    while (begin != end) {
209
9
        ForwardIterator temp = begin;
210
9
        ++begin;
211
9
        delete temp->second;
212
9
    }
213
1
}
214
215
template <typename T>
216
0
inline void STLAssignToVector(vector<T>* vec, const T* ptr, size_t n) {
217
0
    vec->resize(n);
218
0
    if (n == 0) return;
219
0
    memcpy(&vec->front(), ptr, n * sizeof(T));
220
0
}
221
222
// Not faster; but we need the specialization so the function works at all
223
// on the vector<bool> specialization.
224
template <>
225
0
inline void STLAssignToVector(vector<bool>* vec, const bool* ptr, size_t n) {
226
0
    vec->clear();
227
0
    if (n == 0) return;
228
0
    vec->insert(vec->begin(), ptr, ptr + n);
229
0
}
230
231
/***** Hack to allow faster assignment to a vector *****/
232
233
// This routine speeds up an assignment of 32 bytes to a vector from
234
// about 250 cycles per assignment to about 140 cycles.
235
//
236
// Usage:
237
//      STLAssignToVectorChar(&vec, ptr, size);
238
//      STLAssignToString(&str, ptr, size);
239
240
0
inline void STLAssignToVectorChar(vector<char>* vec, const char* ptr, size_t n) {
241
0
    STLAssignToVector(vec, ptr, n);
242
0
}
243
244
// A struct that mirrors the GCC4 implementation of a string. See:
245
// /usr/crosstool/v8/gcc-4.1.0-glibc-2.2.2/i686-unknown-linux-gnu/include/c++/4.1.0/ext/sso_string_base.h
246
struct InternalStringRepGCC4 {
247
    char* _M_data = nullptr;
248
    size_t _M_string_length;
249
250
    enum { _S_local_capacity = 15 };
251
252
    union {
253
        char _M_local_data[_S_local_capacity + 1];
254
        size_t _M_allocated_capacity;
255
    };
256
};
257
258
// Like str->resize(new_size), except any new characters added to
259
// "*str" as a result of resizing may be left uninitialized, rather
260
// than being filled with '0' bytes.  Typically used when code is then
261
// going to overwrite the backing store of the string with known data.
262
117k
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
263
117k
    if (sizeof(*s) == sizeof(InternalStringRepGCC4)) {
264
117k
        if (new_size > s->capacity()) {
265
3.23k
            s->reserve(new_size);
266
3.23k
        }
267
        // The line below depends on the layout of 'string'.  THIS IS
268
        // NON-PORTABLE CODE.  If our STL implementation changes, we will
269
        // need to change this as well.
270
117k
        InternalStringRepGCC4* rep = reinterpret_cast<InternalStringRepGCC4*>(s);
271
117k
        assert(rep->_M_data == s->data());
272
0
        assert(rep->_M_string_length == s->size());
273
274
        // We have to null-terminate the string for c_str() to work properly.
275
        // So we leave the actual contents of the string uninitialized, but
276
        // we set the byte one past the new end of the string to '\0'
277
0
        const_cast<char*>(s->data())[new_size] = '\0';
278
117k
        rep->_M_string_length = new_size;
279
117k
    } else {
280
        // Slow path: have to reallocate stuff, or an unknown string rep
281
0
        s->resize(new_size);
282
0
    }
283
117k
}
284
285
// Returns true if the string implementation supports a resize where
286
// the new characters added to the string are left untouched.
287
0
inline bool STLStringSupportsNontrashingResize(const string& s) {
288
0
    return (sizeof(s) == sizeof(InternalStringRepGCC4));
289
0
}
290
291
0
inline void STLAssignToString(string* str, const char* ptr, size_t n) {
292
0
    STLStringResizeUninitialized(str, n);
293
0
    if (n == 0) return;
294
0
    memcpy(&*str->begin(), ptr, n);
295
0
}
296
297
0
inline void STLAppendToString(string* str, const char* ptr, size_t n) {
298
0
    if (n == 0) return;
299
0
    size_t old_size = str->size();
300
0
    STLStringResizeUninitialized(str, old_size + n);
301
0
    memcpy(&*str->begin() + old_size, ptr, n);
302
0
}
303
304
// To treat a possibly-empty vector as an array, use these functions.
305
// If you know the array will never be empty, you can use &*v.begin()
306
// directly, but that is allowed to dump core if v is empty.  This
307
// function is the most efficient code that will work, taking into
308
// account how our STL is actually implemented.  THIS IS NON-PORTABLE
309
// CODE, so call us instead of repeating the nonportable code
310
// everywhere.  If our STL implementation changes, we will need to
311
// change this as well.
312
313
template <typename T, typename Allocator>
314
 T* vector_as_array(vector<T, Allocator>* v) {
315
#ifdef NDEBUG
316
    return &*v->begin();
317
#else
318
    return v->empty() ? NULL : &*v->begin();
319
#endif
320
}
321
322
template <typename T, typename Allocator>
323
 const T* vector_as_array(const vector<T, Allocator>* v) {
324
#ifdef NDEBUG
325
    return &*v->begin();
326
#else
327
    return v->empty() ? NULL : &*v->begin();
328
#endif
329
}
330
331
// Return a mutable char* pointing to a string's internal buffer,
332
// which may not be null-terminated. Writing through this pointer will
333
// modify the string.
334
//
335
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
336
// next call to a string method that invalidates iterators.
337
//
338
// Prior to C++11, there was no standard-blessed way of getting a mutable
339
// reference to a string's internal buffer. The requirement that string be
340
// contiguous is officially part of the C++11 standard [string.require]/5.
341
// According to Matt Austern, this should already work on all current C++98
342
// implementations.
343
117k
inline char* string_as_array(string* str) {
344
    // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
345
117k
    return str->empty() ? NULL : &*str->begin();
346
117k
}
347
348
// These are methods that test two hash maps/sets for equality.  These exist
349
// because the == operator in the STL can return false when the maps/sets
350
// contain identical elements.  This is because it compares the internal hash
351
// tables which may be different if the order of insertions and deletions
352
// differed.
353
354
template <class HashSet>
355
 bool HashSetEquality(const HashSet& set_a, const HashSet& set_b) {
356
    if (set_a.size() != set_b.size()) return false;
357
    for (typename HashSet::const_iterator i = set_a.begin(); i != set_a.end(); ++i)
358
        if (set_b.find(*i) == set_b.end()) return false;
359
    return true;
360
}
361
362
template <class HashMap>
363
 bool HashMapEquality(const HashMap& map_a, const HashMap& map_b) {
364
    if (map_a.size() != map_b.size()) return false;
365
    for (typename HashMap::const_iterator i = map_a.begin(); i != map_a.end(); ++i) {
366
        typename HashMap::const_iterator j = map_b.find(i->first);
367
        if (j == map_b.end()) return false;
368
        if (i->second != j->second) return false;
369
    }
370
    return true;
371
}
372
373
// The following functions are useful for cleaning up STL containers
374
// whose elements point to allocated memory.
375
376
// STLDeleteElements() deletes all the elements in an STL container and clears
377
// the container.  This function is suitable for use with a vector, set,
378
// hash_set, or any other STL container which defines sensible begin(), end(),
379
// and clear() methods.
380
//
381
// If container is NULL, this function is a no-op.
382
//
383
// As an alternative to calling STLDeleteElements() directly, consider
384
// ElementDeleter (defined below), which ensures that your container's elements
385
// are deleted when the ElementDeleter goes out of scope.
386
template <class T>
387
void STLDeleteElements(T* container) {
388
    if (!container) return;
389
    STLDeleteContainerPointers(container->begin(), container->end());
390
    container->clear();
391
}
392
393
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
394
// deletes all the "value" components and clears the container.  Does nothing
395
// in the case it's given a NULL pointer.
396
template <class T>
397
1
void STLDeleteValues(T* v) {
398
1
    if (!v) return;
399
1
    STLDeleteContainerPairSecondPointers(v->begin(), v->end());
400
1
    v->clear();
401
1
}
402
403
// ElementDeleter and ValueDeleter provide a convenient way to delete all
404
// elements or values from STL containers when they go out of scope.  This
405
// greatly simplifies code that creates temporary objects and has multiple
406
// return statements.  Example:
407
//
408
// vector<MyProto *> tmp_proto;
409
// ElementDeleter d(&tmp_proto);
410
// if (...) return false;
411
// ...
412
// return success;
413
414
// A very simple interface that simply provides a virtual destructor.  It is
415
// used as a non-templated base class for the TemplatedElementDeleter and
416
// TemplatedValueDeleter classes.  Clients should not typically use this class
417
// directly.
418
class BaseDeleter {
419
public:
420
0
    virtual ~BaseDeleter() {}
421
422
protected:
423
0
    BaseDeleter() {}
424
425
private:
426
    DISALLOW_EVIL_CONSTRUCTORS(BaseDeleter);
427
};
428
429
// Given a pointer to an STL container, this class will delete all the element
430
// pointers when it goes out of scope.  Clients should typically use
431
// ElementDeleter rather than invoking this class directly.
432
template <class STLContainer>
433
class TemplatedElementDeleter : public BaseDeleter {
434
public:
435
    explicit TemplatedElementDeleter(STLContainer* ptr) : container_ptr_(ptr) {}
436
437
    virtual ~TemplatedElementDeleter() { STLDeleteElements(container_ptr_); }
438
439
private:
440
    STLContainer* container_ptr_ = nullptr;
441
442
    DISALLOW_EVIL_CONSTRUCTORS(TemplatedElementDeleter);
443
};
444
445
// Like TemplatedElementDeleter, this class will delete element pointers from a
446
// container when it goes out of scope.  However, it is much nicer to use,
447
// since the class itself is not templated.
448
class ElementDeleter {
449
public:
450
    template <class STLContainer>
451
    explicit ElementDeleter(STLContainer* ptr)
452
            : deleter_(new TemplatedElementDeleter<STLContainer>(ptr)) {}
453
454
0
    ~ElementDeleter() { delete deleter_; }
455
456
private:
457
    BaseDeleter* deleter_ = nullptr;
458
459
    DISALLOW_EVIL_CONSTRUCTORS(ElementDeleter);
460
};
461
462
// Given a pointer to an STL container this class will delete all the value
463
// pointers when it goes out of scope.  Clients should typically use
464
// ValueDeleter rather than invoking this class directly.
465
template <class STLContainer>
466
class TemplatedValueDeleter : public BaseDeleter {
467
public:
468
    explicit TemplatedValueDeleter(STLContainer* ptr) : container_ptr_(ptr) {}
469
470
    virtual ~TemplatedValueDeleter() { STLDeleteValues(container_ptr_); }
471
472
private:
473
    STLContainer* container_ptr_ = nullptr;
474
475
    DISALLOW_EVIL_CONSTRUCTORS(TemplatedValueDeleter);
476
};
477
478
// Similar to ElementDeleter, but wraps a TemplatedValueDeleter rather than an
479
// TemplatedElementDeleter.
480
class ValueDeleter {
481
public:
482
    template <class STLContainer>
483
    explicit ValueDeleter(STLContainer* ptr)
484
            : deleter_(new TemplatedValueDeleter<STLContainer>(ptr)) {}
485
486
0
    ~ValueDeleter() { delete deleter_; }
487
488
private:
489
    BaseDeleter* deleter_ = nullptr;
490
491
    DISALLOW_EVIL_CONSTRUCTORS(ValueDeleter);
492
};
493
494
// STLElementDeleter and STLValueDeleter are similar to ElementDeleter and
495
// ValueDeleter, except that:
496
// - The classes are templated, making them less convenient to use.
497
// - Their destructors are not virtual, making them potentially more efficient.
498
// New code should typically use ElementDeleter and ValueDeleter unless
499
// efficiency is a large concern.
500
501
template <class STLContainer>
502
class STLElementDeleter {
503
public:
504
    STLElementDeleter(STLContainer* ptr) : container_ptr_(ptr) {}
505
    ~STLElementDeleter() { STLDeleteElements(container_ptr_); }
506
507
private:
508
    STLContainer* container_ptr_ = nullptr;
509
};
510
511
template <class STLContainer>
512
class STLValueDeleter {
513
public:
514
    STLValueDeleter(STLContainer* ptr) : container_ptr_(ptr) {}
515
    ~STLValueDeleter() { STLDeleteValues(container_ptr_); }
516
517
private:
518
    STLContainer* container_ptr_ = nullptr;
519
};
520
521
// STLSet{Difference,SymmetricDifference,Union,Intersection}(A a, B b, C *c)
522
// *APPEND* the set {difference, symmetric difference, union, intersection} of
523
// the two sets a and b to c.
524
// STLSet{Difference,SymmetricDifference,Union,Intersection}(T a, T b) do the
525
// same but return the result by value rather than by the third pointer
526
// argument.  The result type is the same as both of the inputs in the two
527
// argument case.
528
//
529
// Requires:
530
//   a and b must be STL like containers that contain sorted data (as defined
531
//   by the < operator).
532
//   For the 3 argument version &a == c or &b == c are disallowed.  In those
533
//   cases the 2 argument version is probably what you want anyway:
534
//   a = STLSetDifference(a, b);
535
//
536
// These function are convenience functions.  The code they implement is
537
// trivial (at least for now).  The STL incantations they wrap are just too
538
// verbose for programmers to use then and they are unpleasant to the eye.
539
// Without these convenience versions people will simply keep writing one-off
540
// for loops which are harder to read and more error prone.
541
//
542
// Note that for initial construction of an object it is just as efficient to
543
// use the 2 argument version as the 3 version due to RVO (return value
544
// optimization) of modern C++ compilers:
545
//   set<int> c = STLSetDifference(a, b);
546
// is an example of where RVO comes into play.
547
548
template <typename SortedSTLContainerA, typename SortedSTLContainerB, typename SortedSTLContainerC>
549
void STLSetDifference(const SortedSTLContainerA& a, const SortedSTLContainerB& b,
550
                      SortedSTLContainerC* c) {
551
    // The qualified name avoids an ambiguity error, particularly with C++11:
552
    assert(std::is_sorted(a.begin(), a.end()));
553
    assert(std::is_sorted(b.begin(), b.end()));
554
    assert(static_cast<const void*>(&a) != static_cast<const void*>(c));
555
    assert(static_cast<const void*>(&b) != static_cast<const void*>(c));
556
    std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(*c, c->end()));
557
}
558
559
template <typename SortedSTLContainer>
560
SortedSTLContainer STLSetDifference(const SortedSTLContainer& a, const SortedSTLContainer& b) {
561
    SortedSTLContainer c;
562
    STLSetDifference(a, b, &c);
563
    return c;
564
}
565
566
template <typename SortedSTLContainerA, typename SortedSTLContainerB, typename SortedSTLContainerC>
567
void STLSetUnion(const SortedSTLContainerA& a, const SortedSTLContainerB& b,
568
                 SortedSTLContainerC* c) {
569
    assert(std::is_sorted(a.begin(), a.end()));
570
    assert(std::is_sorted(b.begin(), b.end()));
571
    assert(static_cast<const void*>(&a) != static_cast<const void*>(c));
572
    assert(static_cast<const void*>(&b) != static_cast<const void*>(c));
573
    std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(*c, c->end()));
574
}
575
576
template <typename SortedSTLContainerA, typename SortedSTLContainerB, typename SortedSTLContainerC>
577
void STLSetSymmetricDifference(const SortedSTLContainerA& a, const SortedSTLContainerB& b,
578
                               SortedSTLContainerC* c) {
579
    assert(std::is_sorted(a.begin(), a.end()));
580
    assert(std::is_sorted(b.begin(), b.end()));
581
    assert(static_cast<const void*>(&a) != static_cast<const void*>(c));
582
    assert(static_cast<const void*>(&b) != static_cast<const void*>(c));
583
    std::set_symmetric_difference(a.begin(), a.end(), b.begin(), b.end(),
584
                                  std::inserter(*c, c->end()));
585
}
586
587
template <typename SortedSTLContainer>
588
SortedSTLContainer STLSetSymmetricDifference(const SortedSTLContainer& a,
589
                                             const SortedSTLContainer& b) {
590
    SortedSTLContainer c;
591
    STLSetSymmetricDifference(a, b, &c);
592
    return c;
593
}
594
595
template <typename SortedSTLContainer>
596
SortedSTLContainer STLSetUnion(const SortedSTLContainer& a, const SortedSTLContainer& b) {
597
    SortedSTLContainer c;
598
    STLSetUnion(a, b, &c);
599
    return c;
600
}
601
602
template <typename SortedSTLContainerA, typename SortedSTLContainerB, typename SortedSTLContainerC>
603
void STLSetIntersection(const SortedSTLContainerA& a, const SortedSTLContainerB& b,
604
                        SortedSTLContainerC* c) {
605
    assert(std::is_sorted(a.begin(), a.end()));
606
    assert(std::is_sorted(b.begin(), b.end()));
607
    assert(static_cast<const void*>(&a) != static_cast<const void*>(c));
608
    assert(static_cast<const void*>(&b) != static_cast<const void*>(c));
609
    std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(*c, c->end()));
610
}
611
612
template <typename SortedSTLContainer>
613
SortedSTLContainer STLSetIntersection(const SortedSTLContainer& a, const SortedSTLContainer& b) {
614
    SortedSTLContainer c;
615
    STLSetIntersection(a, b, &c);
616
    return c;
617
}
618
619
// Similar to STLSet{Union,Intesection,etc}, but simpler because the result is
620
// always bool.
621
template <typename SortedSTLContainerA, typename SortedSTLContainerB>
622
bool STLIncludes(const SortedSTLContainerA& a, const SortedSTLContainerB& b) {
623
    assert(std::is_sorted(a.begin(), a.end()));
624
    assert(std::is_sorted(b.begin(), b.end()));
625
    return std::includes(a.begin(), a.end(), b.begin(), b.end());
626
}
627
628
// Functors that compose arbitrary unary and binary functions with a
629
// function that "projects" one of the members of a pair.
630
// Specifically, if p1 and p2, respectively, are the functions that
631
// map a pair to its first and second, respectively, members, the
632
// table below summarizes the functions that can be constructed:
633
//
634
// * UnaryOperate1st<pair>(f) returns the function x -> f(p1(x))
635
// * UnaryOperate2nd<pair>(f) returns the function x -> f(p2(x))
636
// * BinaryOperate1st<pair>(f) returns the function (x,y) -> f(p1(x),p1(y))
637
// * BinaryOperate2nd<pair>(f) returns the function (x,y) -> f(p2(x),p2(y))
638
//
639
// A typical usage for these functions would be when iterating over
640
// the contents of an STL map. For other sample usage, see the unittest.
641
642
template <typename Pair, typename UnaryOp>
643
class UnaryOperateOnFirst {
644
public:
645
    UnaryOperateOnFirst() {}
646
647
    UnaryOperateOnFirst(const UnaryOp& f) : f_(f) { // TODO(user): explicit?
648
    }
649
650
    typename UnaryOp::result_type operator()(const Pair& p) const { return f_(p.first); }
651
652
private:
653
    UnaryOp f_;
654
};
655
656
template <typename Pair, typename UnaryOp>
657
UnaryOperateOnFirst<Pair, UnaryOp> UnaryOperate1st(const UnaryOp& f) {
658
    return UnaryOperateOnFirst<Pair, UnaryOp>(f);
659
}
660
661
template <typename Pair, typename UnaryOp>
662
class UnaryOperateOnSecond {
663
public:
664
    UnaryOperateOnSecond() {}
665
666
    UnaryOperateOnSecond(const UnaryOp& f) : f_(f) { // TODO(user): explicit?
667
    }
668
669
    typename UnaryOp::result_type operator()(const Pair& p) const { return f_(p.second); }
670
671
private:
672
    UnaryOp f_;
673
};
674
675
template <typename Pair, typename UnaryOp>
676
UnaryOperateOnSecond<Pair, UnaryOp> UnaryOperate2nd(const UnaryOp& f) {
677
    return UnaryOperateOnSecond<Pair, UnaryOp>(f);
678
}
679
680
template <typename Pair, typename BinaryOp>
681
class BinaryOperateOnFirst {
682
public:
683
    BinaryOperateOnFirst() {}
684
685
    BinaryOperateOnFirst(const BinaryOp& f) : f_(f) { // TODO(user): explicit?
686
    }
687
688
    typename BinaryOp::result_type operator()(const Pair& p1, const Pair& p2) const {
689
        return f_(p1.first, p2.first);
690
    }
691
692
private:
693
    BinaryOp f_;
694
};
695
696
// TODO(user): explicit?
697
template <typename Pair, typename BinaryOp>
698
BinaryOperateOnFirst<Pair, BinaryOp> BinaryOperate1st(const BinaryOp& f) {
699
    return BinaryOperateOnFirst<Pair, BinaryOp>(f);
700
}
701
702
template <typename Pair, typename BinaryOp>
703
class BinaryOperateOnSecond {
704
public:
705
    BinaryOperateOnSecond() {}
706
707
    BinaryOperateOnSecond(const BinaryOp& f) : f_(f) {}
708
709
    typename BinaryOp::result_type operator()(const Pair& p1, const Pair& p2) const {
710
        return f_(p1.second, p2.second);
711
    }
712
713
private:
714
    BinaryOp f_;
715
};
716
717
template <typename Pair, typename BinaryOp>
718
BinaryOperateOnSecond<Pair, BinaryOp> BinaryOperate2nd(const BinaryOp& f) {
719
    return BinaryOperateOnSecond<Pair, BinaryOp>(f);
720
}
721
722
// Functor that composes a binary functor h from an arbitrary binary functor
723
// f and two unary functors g1, g2, so that:
724
//
725
// BinaryCompose1(f, g) returns function (x, y) -> f(g(x), g(y))
726
// BinaryCompose2(f, g1, g2) returns function (x, y) -> f(g1(x), g2(y))
727
//
728
// This is a generalization of the BinaryOperate* functors for types other
729
// than pairs.
730
//
731
// For sample usage, see the unittest.
732
//
733
// F has to be a model of AdaptableBinaryFunction.
734
// G1 and G2 have to be models of AdabtableUnaryFunction.
735
template <typename F, typename G1, typename G2>
736
class BinaryComposeBinary {
737
public:
738
    BinaryComposeBinary(F f, G1 g1, G2 g2) : f_(f), g1_(g1), g2_(g2) {}
739
740
    typename F::result_type operator()(typename G1::argument_type x,
741
                                       typename G2::argument_type y) const {
742
        return f_(g1_(x), g2_(y));
743
    }
744
745
private:
746
    F f_;
747
    G1 g1_;
748
    G2 g2_;
749
};
750
751
template <typename F, typename G>
752
BinaryComposeBinary<F, G, G> BinaryCompose1(F f, G g) {
753
    return BinaryComposeBinary<F, G, G>(f, g, g);
754
}
755
756
template <typename F, typename G1, typename G2>
757
BinaryComposeBinary<F, G1, G2> BinaryCompose2(F f, G1 g1, G2 g2) {
758
    return BinaryComposeBinary<F, G1, G2>(f, g1, g2);
759
}
760
761
// Even though a struct has no data members, it cannot have zero size
762
// according to the standard.  However, "empty base-class
763
// optimization" allows an empty parent class to add no additional
764
// size to the object.  STLEmptyBaseHandle is a handy way to "stuff"
765
// objects that are typically empty (e.g., allocators, compare
766
// objects) into other fields of an object without increasing the size
767
// of the object.
768
//
769
// struct Empty {
770
//   void Method() { }
771
// };
772
// struct OneInt {
773
//   STLEmptyBaseHandle<Empty, int> i;
774
// };
775
//
776
// In the example above, "i.data" refers to the integer field, whereas
777
// "i" refers to the empty base class.  sizeof(OneInt) == sizeof(int)
778
// despite the fact that sizeof(Empty) > 0.
779
template <typename Base, typename Data>
780
struct STLEmptyBaseHandle : public Base {
781
    template <typename U>
782
    STLEmptyBaseHandle(const U& b, const Data& d) : Base(b), data(d) {}
783
    Data data;
784
};
785
786
// These functions return true if there is some element in the sorted range
787
// [begin1, end) which is equal to some element in the sorted range [begin2,
788
// end2). The iterators do not have to be of the same type, but the value types
789
// must be less-than comparable. (Two elements a,b are considered equal if
790
// !(a < b) && !(b < a).
791
template <typename InputIterator1, typename InputIterator2>
792
bool SortedRangesHaveIntersection(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
793
                                  InputIterator2 end2) {
794
    assert(std::is_sorted(begin1, end1));
795
    assert(std::is_sorted(begin2, end2));
796
    while (begin1 != end1 && begin2 != end2) {
797
        if (*begin1 < *begin2) {
798
            ++begin1;
799
        } else if (*begin2 < *begin1) {
800
            ++begin2;
801
        } else {
802
            return true;
803
        }
804
    }
805
    return false;
806
}
807
808
// This is equivalent to the function above, but using a custom comparison
809
// function.
810
template <typename InputIterator1, typename InputIterator2, typename Comp>
811
bool SortedRangesHaveIntersection(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
812
                                  InputIterator2 end2, Comp comparator) {
813
    assert(std::is_sorted(begin1, end1, comparator));
814
    assert(std::is_sorted(begin2, end2, comparator));
815
    while (begin1 != end1 && begin2 != end2) {
816
        if (comparator(*begin1, *begin2)) {
817
            ++begin1;
818
        } else if (comparator(*begin2, *begin1)) {
819
            ++begin2;
820
        } else {
821
            return true;
822
        }
823
    }
824
    return false;
825
}
826
827
// release_ptr is intended to help remove systematic use of gscoped_ptr
828
// in cases like:
829
//
830
// vector<Foo *> v;
831
// ElementDeleter d(&v);
832
// ... {
833
//   int remove_idx = f(v);
834
//   gscoped_ptr<Foo> t(v[remove_idx]);
835
//   v[remove_idx] = NULL;  // Save from deleter.
836
//   return t.release();
837
// }
838
//
839
// This would be replaced by:
840
// ... {
841
//   int remove_idx = f(v);
842
//   return release_ptr(&v[remove_idx]);
843
// }
844
template <typename T>
845
T* release_ptr(T** ptr) MUST_USE_RESULT;
846
template <typename T>
847
T* release_ptr(T** ptr) {
848
    assert(ptr);
849
    T* tmp = *ptr;
850
    *ptr = NULL;
851
    return tmp;
852
}