xref: /aosp_15_r20/external/libchrome/base/stl_util.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker // Derived from google3/util/gtl/stl_util.h
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #ifndef BASE_STL_UTIL_H_
8*635a8641SAndroid Build Coastguard Worker #define BASE_STL_UTIL_H_
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <algorithm>
11*635a8641SAndroid Build Coastguard Worker #include <deque>
12*635a8641SAndroid Build Coastguard Worker #include <forward_list>
13*635a8641SAndroid Build Coastguard Worker #include <functional>
14*635a8641SAndroid Build Coastguard Worker #include <initializer_list>
15*635a8641SAndroid Build Coastguard Worker #include <iterator>
16*635a8641SAndroid Build Coastguard Worker #include <list>
17*635a8641SAndroid Build Coastguard Worker #include <map>
18*635a8641SAndroid Build Coastguard Worker #include <set>
19*635a8641SAndroid Build Coastguard Worker #include <string>
20*635a8641SAndroid Build Coastguard Worker #include <unordered_map>
21*635a8641SAndroid Build Coastguard Worker #include <unordered_set>
22*635a8641SAndroid Build Coastguard Worker #include <vector>
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
25*635a8641SAndroid Build Coastguard Worker #include "base/optional.h"
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker namespace base {
28*635a8641SAndroid Build Coastguard Worker 
29*635a8641SAndroid Build Coastguard Worker namespace internal {
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker // Calls erase on iterators of matching elements.
32*635a8641SAndroid Build Coastguard Worker template <typename Container, typename Predicate>
IterateAndEraseIf(Container & container,Predicate pred)33*635a8641SAndroid Build Coastguard Worker void IterateAndEraseIf(Container& container, Predicate pred) {
34*635a8641SAndroid Build Coastguard Worker   for (auto it = container.begin(); it != container.end();) {
35*635a8641SAndroid Build Coastguard Worker     if (pred(*it))
36*635a8641SAndroid Build Coastguard Worker       it = container.erase(it);
37*635a8641SAndroid Build Coastguard Worker     else
38*635a8641SAndroid Build Coastguard Worker       ++it;
39*635a8641SAndroid Build Coastguard Worker   }
40*635a8641SAndroid Build Coastguard Worker }
41*635a8641SAndroid Build Coastguard Worker 
42*635a8641SAndroid Build Coastguard Worker }  // namespace internal
43*635a8641SAndroid Build Coastguard Worker 
44*635a8641SAndroid Build Coastguard Worker // C++14 implementation of C++17's std::size():
45*635a8641SAndroid Build Coastguard Worker // http://en.cppreference.com/w/cpp/iterator/size
46*635a8641SAndroid Build Coastguard Worker template <typename Container>
47*635a8641SAndroid Build Coastguard Worker constexpr auto size(const Container& c) -> decltype(c.size()) {
48*635a8641SAndroid Build Coastguard Worker   return c.size();
49*635a8641SAndroid Build Coastguard Worker }
50*635a8641SAndroid Build Coastguard Worker 
51*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
size(const T (& array)[N])52*635a8641SAndroid Build Coastguard Worker constexpr size_t size(const T (&array)[N]) noexcept {
53*635a8641SAndroid Build Coastguard Worker   return N;
54*635a8641SAndroid Build Coastguard Worker }
55*635a8641SAndroid Build Coastguard Worker 
56*635a8641SAndroid Build Coastguard Worker // C++14 implementation of C++17's std::empty():
57*635a8641SAndroid Build Coastguard Worker // http://en.cppreference.com/w/cpp/iterator/empty
58*635a8641SAndroid Build Coastguard Worker template <typename Container>
59*635a8641SAndroid Build Coastguard Worker constexpr auto empty(const Container& c) -> decltype(c.empty()) {
60*635a8641SAndroid Build Coastguard Worker   return c.empty();
61*635a8641SAndroid Build Coastguard Worker }
62*635a8641SAndroid Build Coastguard Worker 
63*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
empty(const T (& array)[N])64*635a8641SAndroid Build Coastguard Worker constexpr bool empty(const T (&array)[N]) noexcept {
65*635a8641SAndroid Build Coastguard Worker   return false;
66*635a8641SAndroid Build Coastguard Worker }
67*635a8641SAndroid Build Coastguard Worker 
68*635a8641SAndroid Build Coastguard Worker template <typename T>
empty(std::initializer_list<T> il)69*635a8641SAndroid Build Coastguard Worker constexpr bool empty(std::initializer_list<T> il) noexcept {
70*635a8641SAndroid Build Coastguard Worker   return il.size() == 0;
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker // C++14 implementation of C++17's std::data():
74*635a8641SAndroid Build Coastguard Worker // http://en.cppreference.com/w/cpp/iterator/data
75*635a8641SAndroid Build Coastguard Worker template <typename Container>
76*635a8641SAndroid Build Coastguard Worker constexpr auto data(Container& c) -> decltype(c.data()) {
77*635a8641SAndroid Build Coastguard Worker   return c.data();
78*635a8641SAndroid Build Coastguard Worker }
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker // std::basic_string::data() had no mutable overload prior to C++17 [1].
81*635a8641SAndroid Build Coastguard Worker // Hence this overload is provided.
82*635a8641SAndroid Build Coastguard Worker // Note: str[0] is safe even for empty strings, as they are guaranteed to be
83*635a8641SAndroid Build Coastguard Worker // null-terminated [2].
84*635a8641SAndroid Build Coastguard Worker //
85*635a8641SAndroid Build Coastguard Worker // [1] http://en.cppreference.com/w/cpp/string/basic_string/data
86*635a8641SAndroid Build Coastguard Worker // [2] http://en.cppreference.com/w/cpp/string/basic_string/operator_at
87*635a8641SAndroid Build Coastguard Worker template <typename CharT, typename Traits, typename Allocator>
data(std::basic_string<CharT,Traits,Allocator> & str)88*635a8641SAndroid Build Coastguard Worker CharT* data(std::basic_string<CharT, Traits, Allocator>& str) {
89*635a8641SAndroid Build Coastguard Worker   return std::addressof(str[0]);
90*635a8641SAndroid Build Coastguard Worker }
91*635a8641SAndroid Build Coastguard Worker 
92*635a8641SAndroid Build Coastguard Worker template <typename Container>
93*635a8641SAndroid Build Coastguard Worker constexpr auto data(const Container& c) -> decltype(c.data()) {
94*635a8641SAndroid Build Coastguard Worker   return c.data();
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker 
97*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
data(T (& array)[N])98*635a8641SAndroid Build Coastguard Worker constexpr T* data(T (&array)[N]) noexcept {
99*635a8641SAndroid Build Coastguard Worker   return array;
100*635a8641SAndroid Build Coastguard Worker }
101*635a8641SAndroid Build Coastguard Worker 
102*635a8641SAndroid Build Coastguard Worker template <typename T>
data(std::initializer_list<T> il)103*635a8641SAndroid Build Coastguard Worker constexpr const T* data(std::initializer_list<T> il) noexcept {
104*635a8641SAndroid Build Coastguard Worker   return il.begin();
105*635a8641SAndroid Build Coastguard Worker }
106*635a8641SAndroid Build Coastguard Worker 
107*635a8641SAndroid Build Coastguard Worker // Returns a const reference to the underlying container of a container adapter.
108*635a8641SAndroid Build Coastguard Worker // Works for std::priority_queue, std::queue, and std::stack.
109*635a8641SAndroid Build Coastguard Worker template <class A>
GetUnderlyingContainer(const A & adapter)110*635a8641SAndroid Build Coastguard Worker const typename A::container_type& GetUnderlyingContainer(const A& adapter) {
111*635a8641SAndroid Build Coastguard Worker   struct ExposedAdapter : A {
112*635a8641SAndroid Build Coastguard Worker     using A::c;
113*635a8641SAndroid Build Coastguard Worker   };
114*635a8641SAndroid Build Coastguard Worker   return adapter.*&ExposedAdapter::c;
115*635a8641SAndroid Build Coastguard Worker }
116*635a8641SAndroid Build Coastguard Worker 
117*635a8641SAndroid Build Coastguard Worker // Clears internal memory of an STL object.
118*635a8641SAndroid Build Coastguard Worker // STL clear()/reserve(0) does not always free internal memory allocated
119*635a8641SAndroid Build Coastguard Worker // This function uses swap/destructor to ensure the internal memory is freed.
120*635a8641SAndroid Build Coastguard Worker template<class T>
STLClearObject(T * obj)121*635a8641SAndroid Build Coastguard Worker void STLClearObject(T* obj) {
122*635a8641SAndroid Build Coastguard Worker   T tmp;
123*635a8641SAndroid Build Coastguard Worker   tmp.swap(*obj);
124*635a8641SAndroid Build Coastguard Worker   // Sometimes "T tmp" allocates objects with memory (arena implementation?).
125*635a8641SAndroid Build Coastguard Worker   // Hence using additional reserve(0) even if it doesn't always work.
126*635a8641SAndroid Build Coastguard Worker   obj->reserve(0);
127*635a8641SAndroid Build Coastguard Worker }
128*635a8641SAndroid Build Coastguard Worker 
129*635a8641SAndroid Build Coastguard Worker // Counts the number of instances of val in a container.
130*635a8641SAndroid Build Coastguard Worker template <typename Container, typename T>
131*635a8641SAndroid Build Coastguard Worker typename std::iterator_traits<
132*635a8641SAndroid Build Coastguard Worker     typename Container::const_iterator>::difference_type
STLCount(const Container & container,const T & val)133*635a8641SAndroid Build Coastguard Worker STLCount(const Container& container, const T& val) {
134*635a8641SAndroid Build Coastguard Worker   return std::count(container.begin(), container.end(), val);
135*635a8641SAndroid Build Coastguard Worker }
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker // Test to see if a set or map contains a particular key.
138*635a8641SAndroid Build Coastguard Worker // Returns true if the key is in the collection.
139*635a8641SAndroid Build Coastguard Worker template <typename Collection, typename Key>
ContainsKey(const Collection & collection,const Key & key)140*635a8641SAndroid Build Coastguard Worker bool ContainsKey(const Collection& collection, const Key& key) {
141*635a8641SAndroid Build Coastguard Worker   return collection.find(key) != collection.end();
142*635a8641SAndroid Build Coastguard Worker }
143*635a8641SAndroid Build Coastguard Worker 
144*635a8641SAndroid Build Coastguard Worker namespace internal {
145*635a8641SAndroid Build Coastguard Worker 
146*635a8641SAndroid Build Coastguard Worker template <typename Collection>
147*635a8641SAndroid Build Coastguard Worker class HasKeyType {
148*635a8641SAndroid Build Coastguard Worker   template <typename C>
149*635a8641SAndroid Build Coastguard Worker   static std::true_type test(typename C::key_type*);
150*635a8641SAndroid Build Coastguard Worker   template <typename C>
151*635a8641SAndroid Build Coastguard Worker   static std::false_type test(...);
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker  public:
154*635a8641SAndroid Build Coastguard Worker   static constexpr bool value = decltype(test<Collection>(nullptr))::value;
155*635a8641SAndroid Build Coastguard Worker };
156*635a8641SAndroid Build Coastguard Worker 
157*635a8641SAndroid Build Coastguard Worker }  // namespace internal
158*635a8641SAndroid Build Coastguard Worker 
159*635a8641SAndroid Build Coastguard Worker // Test to see if a collection like a vector contains a particular value.
160*635a8641SAndroid Build Coastguard Worker // Returns true if the value is in the collection.
161*635a8641SAndroid Build Coastguard Worker // Don't use this on collections such as sets or maps. This is enforced by
162*635a8641SAndroid Build Coastguard Worker // disabling this method if the collection defines a key_type.
163*635a8641SAndroid Build Coastguard Worker template <typename Collection,
164*635a8641SAndroid Build Coastguard Worker           typename Value,
165*635a8641SAndroid Build Coastguard Worker           typename std::enable_if<!internal::HasKeyType<Collection>::value,
166*635a8641SAndroid Build Coastguard Worker                                   int>::type = 0>
ContainsValue(const Collection & collection,const Value & value)167*635a8641SAndroid Build Coastguard Worker bool ContainsValue(const Collection& collection, const Value& value) {
168*635a8641SAndroid Build Coastguard Worker   return std::find(std::begin(collection), std::end(collection), value) !=
169*635a8641SAndroid Build Coastguard Worker          std::end(collection);
170*635a8641SAndroid Build Coastguard Worker }
171*635a8641SAndroid Build Coastguard Worker 
172*635a8641SAndroid Build Coastguard Worker // Returns true if the container is sorted.
173*635a8641SAndroid Build Coastguard Worker template <typename Container>
STLIsSorted(const Container & cont)174*635a8641SAndroid Build Coastguard Worker bool STLIsSorted(const Container& cont) {
175*635a8641SAndroid Build Coastguard Worker   // Note: Use reverse iterator on container to ensure we only require
176*635a8641SAndroid Build Coastguard Worker   // value_type to implement operator<.
177*635a8641SAndroid Build Coastguard Worker   return std::adjacent_find(cont.rbegin(), cont.rend(),
178*635a8641SAndroid Build Coastguard Worker                             std::less<typename Container::value_type>())
179*635a8641SAndroid Build Coastguard Worker       == cont.rend();
180*635a8641SAndroid Build Coastguard Worker }
181*635a8641SAndroid Build Coastguard Worker 
182*635a8641SAndroid Build Coastguard Worker // Returns a new ResultType containing the difference of two sorted containers.
183*635a8641SAndroid Build Coastguard Worker template <typename ResultType, typename Arg1, typename Arg2>
STLSetDifference(const Arg1 & a1,const Arg2 & a2)184*635a8641SAndroid Build Coastguard Worker ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
185*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a1));
186*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a2));
187*635a8641SAndroid Build Coastguard Worker   ResultType difference;
188*635a8641SAndroid Build Coastguard Worker   std::set_difference(a1.begin(), a1.end(),
189*635a8641SAndroid Build Coastguard Worker                       a2.begin(), a2.end(),
190*635a8641SAndroid Build Coastguard Worker                       std::inserter(difference, difference.end()));
191*635a8641SAndroid Build Coastguard Worker   return difference;
192*635a8641SAndroid Build Coastguard Worker }
193*635a8641SAndroid Build Coastguard Worker 
194*635a8641SAndroid Build Coastguard Worker // Returns a new ResultType containing the union of two sorted containers.
195*635a8641SAndroid Build Coastguard Worker template <typename ResultType, typename Arg1, typename Arg2>
STLSetUnion(const Arg1 & a1,const Arg2 & a2)196*635a8641SAndroid Build Coastguard Worker ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) {
197*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a1));
198*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a2));
199*635a8641SAndroid Build Coastguard Worker   ResultType result;
200*635a8641SAndroid Build Coastguard Worker   std::set_union(a1.begin(), a1.end(),
201*635a8641SAndroid Build Coastguard Worker                  a2.begin(), a2.end(),
202*635a8641SAndroid Build Coastguard Worker                  std::inserter(result, result.end()));
203*635a8641SAndroid Build Coastguard Worker   return result;
204*635a8641SAndroid Build Coastguard Worker }
205*635a8641SAndroid Build Coastguard Worker 
206*635a8641SAndroid Build Coastguard Worker // Returns a new ResultType containing the intersection of two sorted
207*635a8641SAndroid Build Coastguard Worker // containers.
208*635a8641SAndroid Build Coastguard Worker template <typename ResultType, typename Arg1, typename Arg2>
STLSetIntersection(const Arg1 & a1,const Arg2 & a2)209*635a8641SAndroid Build Coastguard Worker ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) {
210*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a1));
211*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a2));
212*635a8641SAndroid Build Coastguard Worker   ResultType result;
213*635a8641SAndroid Build Coastguard Worker   std::set_intersection(a1.begin(), a1.end(),
214*635a8641SAndroid Build Coastguard Worker                         a2.begin(), a2.end(),
215*635a8641SAndroid Build Coastguard Worker                         std::inserter(result, result.end()));
216*635a8641SAndroid Build Coastguard Worker   return result;
217*635a8641SAndroid Build Coastguard Worker }
218*635a8641SAndroid Build Coastguard Worker 
219*635a8641SAndroid Build Coastguard Worker // Returns true if the sorted container |a1| contains all elements of the sorted
220*635a8641SAndroid Build Coastguard Worker // container |a2|.
221*635a8641SAndroid Build Coastguard Worker template <typename Arg1, typename Arg2>
STLIncludes(const Arg1 & a1,const Arg2 & a2)222*635a8641SAndroid Build Coastguard Worker bool STLIncludes(const Arg1& a1, const Arg2& a2) {
223*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a1));
224*635a8641SAndroid Build Coastguard Worker   DCHECK(STLIsSorted(a2));
225*635a8641SAndroid Build Coastguard Worker   return std::includes(a1.begin(), a1.end(),
226*635a8641SAndroid Build Coastguard Worker                        a2.begin(), a2.end());
227*635a8641SAndroid Build Coastguard Worker }
228*635a8641SAndroid Build Coastguard Worker 
229*635a8641SAndroid Build Coastguard Worker // Erase/EraseIf are based on library fundamentals ts v2 erase/erase_if
230*635a8641SAndroid Build Coastguard Worker // http://en.cppreference.com/w/cpp/experimental/lib_extensions_2
231*635a8641SAndroid Build Coastguard Worker // They provide a generic way to erase elements from a container.
232*635a8641SAndroid Build Coastguard Worker // The functions here implement these for the standard containers until those
233*635a8641SAndroid Build Coastguard Worker // functions are available in the C++ standard.
234*635a8641SAndroid Build Coastguard Worker // For Chromium containers overloads should be defined in their own headers
235*635a8641SAndroid Build Coastguard Worker // (like standard containers).
236*635a8641SAndroid Build Coastguard Worker // Note: there is no std::erase for standard associative containers so we don't
237*635a8641SAndroid Build Coastguard Worker // have it either.
238*635a8641SAndroid Build Coastguard Worker 
239*635a8641SAndroid Build Coastguard Worker template <typename CharT, typename Traits, typename Allocator, typename Value>
Erase(std::basic_string<CharT,Traits,Allocator> & container,const Value & value)240*635a8641SAndroid Build Coastguard Worker void Erase(std::basic_string<CharT, Traits, Allocator>& container,
241*635a8641SAndroid Build Coastguard Worker            const Value& value) {
242*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove(container.begin(), container.end(), value),
243*635a8641SAndroid Build Coastguard Worker                   container.end());
244*635a8641SAndroid Build Coastguard Worker }
245*635a8641SAndroid Build Coastguard Worker 
246*635a8641SAndroid Build Coastguard Worker template <typename CharT, typename Traits, typename Allocator, class Predicate>
EraseIf(std::basic_string<CharT,Traits,Allocator> & container,Predicate pred)247*635a8641SAndroid Build Coastguard Worker void EraseIf(std::basic_string<CharT, Traits, Allocator>& container,
248*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
249*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove_if(container.begin(), container.end(), pred),
250*635a8641SAndroid Build Coastguard Worker                   container.end());
251*635a8641SAndroid Build Coastguard Worker }
252*635a8641SAndroid Build Coastguard Worker 
253*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Value>
Erase(std::deque<T,Allocator> & container,const Value & value)254*635a8641SAndroid Build Coastguard Worker void Erase(std::deque<T, Allocator>& container, const Value& value) {
255*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove(container.begin(), container.end(), value),
256*635a8641SAndroid Build Coastguard Worker                   container.end());
257*635a8641SAndroid Build Coastguard Worker }
258*635a8641SAndroid Build Coastguard Worker 
259*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Predicate>
EraseIf(std::deque<T,Allocator> & container,Predicate pred)260*635a8641SAndroid Build Coastguard Worker void EraseIf(std::deque<T, Allocator>& container, Predicate pred) {
261*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove_if(container.begin(), container.end(), pred),
262*635a8641SAndroid Build Coastguard Worker                   container.end());
263*635a8641SAndroid Build Coastguard Worker }
264*635a8641SAndroid Build Coastguard Worker 
265*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Value>
Erase(std::vector<T,Allocator> & container,const Value & value)266*635a8641SAndroid Build Coastguard Worker void Erase(std::vector<T, Allocator>& container, const Value& value) {
267*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove(container.begin(), container.end(), value),
268*635a8641SAndroid Build Coastguard Worker                   container.end());
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker 
271*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Predicate>
EraseIf(std::vector<T,Allocator> & container,Predicate pred)272*635a8641SAndroid Build Coastguard Worker void EraseIf(std::vector<T, Allocator>& container, Predicate pred) {
273*635a8641SAndroid Build Coastguard Worker   container.erase(std::remove_if(container.begin(), container.end(), pred),
274*635a8641SAndroid Build Coastguard Worker                   container.end());
275*635a8641SAndroid Build Coastguard Worker }
276*635a8641SAndroid Build Coastguard Worker 
277*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Value>
Erase(std::forward_list<T,Allocator> & container,const Value & value)278*635a8641SAndroid Build Coastguard Worker void Erase(std::forward_list<T, Allocator>& container, const Value& value) {
279*635a8641SAndroid Build Coastguard Worker   // Unlike std::forward_list::remove, this function template accepts
280*635a8641SAndroid Build Coastguard Worker   // heterogeneous types and does not force a conversion to the container's
281*635a8641SAndroid Build Coastguard Worker   // value type before invoking the == operator.
282*635a8641SAndroid Build Coastguard Worker   container.remove_if([&](const T& cur) { return cur == value; });
283*635a8641SAndroid Build Coastguard Worker }
284*635a8641SAndroid Build Coastguard Worker 
285*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Predicate>
EraseIf(std::forward_list<T,Allocator> & container,Predicate pred)286*635a8641SAndroid Build Coastguard Worker void EraseIf(std::forward_list<T, Allocator>& container, Predicate pred) {
287*635a8641SAndroid Build Coastguard Worker   container.remove_if(pred);
288*635a8641SAndroid Build Coastguard Worker }
289*635a8641SAndroid Build Coastguard Worker 
290*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Value>
Erase(std::list<T,Allocator> & container,const Value & value)291*635a8641SAndroid Build Coastguard Worker void Erase(std::list<T, Allocator>& container, const Value& value) {
292*635a8641SAndroid Build Coastguard Worker   // Unlike std::list::remove, this function template accepts heterogeneous
293*635a8641SAndroid Build Coastguard Worker   // types and does not force a conversion to the container's value type before
294*635a8641SAndroid Build Coastguard Worker   // invoking the == operator.
295*635a8641SAndroid Build Coastguard Worker   container.remove_if([&](const T& cur) { return cur == value; });
296*635a8641SAndroid Build Coastguard Worker }
297*635a8641SAndroid Build Coastguard Worker 
298*635a8641SAndroid Build Coastguard Worker template <class T, class Allocator, class Predicate>
EraseIf(std::list<T,Allocator> & container,Predicate pred)299*635a8641SAndroid Build Coastguard Worker void EraseIf(std::list<T, Allocator>& container, Predicate pred) {
300*635a8641SAndroid Build Coastguard Worker   container.remove_if(pred);
301*635a8641SAndroid Build Coastguard Worker }
302*635a8641SAndroid Build Coastguard Worker 
303*635a8641SAndroid Build Coastguard Worker template <class Key, class T, class Compare, class Allocator, class Predicate>
EraseIf(std::map<Key,T,Compare,Allocator> & container,Predicate pred)304*635a8641SAndroid Build Coastguard Worker void EraseIf(std::map<Key, T, Compare, Allocator>& container, Predicate pred) {
305*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker 
308*635a8641SAndroid Build Coastguard Worker template <class Key, class T, class Compare, class Allocator, class Predicate>
EraseIf(std::multimap<Key,T,Compare,Allocator> & container,Predicate pred)309*635a8641SAndroid Build Coastguard Worker void EraseIf(std::multimap<Key, T, Compare, Allocator>& container,
310*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
311*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
312*635a8641SAndroid Build Coastguard Worker }
313*635a8641SAndroid Build Coastguard Worker 
314*635a8641SAndroid Build Coastguard Worker template <class Key, class Compare, class Allocator, class Predicate>
EraseIf(std::set<Key,Compare,Allocator> & container,Predicate pred)315*635a8641SAndroid Build Coastguard Worker void EraseIf(std::set<Key, Compare, Allocator>& container, Predicate pred) {
316*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
317*635a8641SAndroid Build Coastguard Worker }
318*635a8641SAndroid Build Coastguard Worker 
319*635a8641SAndroid Build Coastguard Worker template <class Key, class Compare, class Allocator, class Predicate>
EraseIf(std::multiset<Key,Compare,Allocator> & container,Predicate pred)320*635a8641SAndroid Build Coastguard Worker void EraseIf(std::multiset<Key, Compare, Allocator>& container,
321*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
322*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
323*635a8641SAndroid Build Coastguard Worker }
324*635a8641SAndroid Build Coastguard Worker 
325*635a8641SAndroid Build Coastguard Worker template <class Key,
326*635a8641SAndroid Build Coastguard Worker           class T,
327*635a8641SAndroid Build Coastguard Worker           class Hash,
328*635a8641SAndroid Build Coastguard Worker           class KeyEqual,
329*635a8641SAndroid Build Coastguard Worker           class Allocator,
330*635a8641SAndroid Build Coastguard Worker           class Predicate>
EraseIf(std::unordered_map<Key,T,Hash,KeyEqual,Allocator> & container,Predicate pred)331*635a8641SAndroid Build Coastguard Worker void EraseIf(std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& container,
332*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
333*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
334*635a8641SAndroid Build Coastguard Worker }
335*635a8641SAndroid Build Coastguard Worker 
336*635a8641SAndroid Build Coastguard Worker template <class Key,
337*635a8641SAndroid Build Coastguard Worker           class T,
338*635a8641SAndroid Build Coastguard Worker           class Hash,
339*635a8641SAndroid Build Coastguard Worker           class KeyEqual,
340*635a8641SAndroid Build Coastguard Worker           class Allocator,
341*635a8641SAndroid Build Coastguard Worker           class Predicate>
EraseIf(std::unordered_multimap<Key,T,Hash,KeyEqual,Allocator> & container,Predicate pred)342*635a8641SAndroid Build Coastguard Worker void EraseIf(
343*635a8641SAndroid Build Coastguard Worker     std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& container,
344*635a8641SAndroid Build Coastguard Worker     Predicate pred) {
345*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
346*635a8641SAndroid Build Coastguard Worker }
347*635a8641SAndroid Build Coastguard Worker 
348*635a8641SAndroid Build Coastguard Worker template <class Key,
349*635a8641SAndroid Build Coastguard Worker           class Hash,
350*635a8641SAndroid Build Coastguard Worker           class KeyEqual,
351*635a8641SAndroid Build Coastguard Worker           class Allocator,
352*635a8641SAndroid Build Coastguard Worker           class Predicate>
EraseIf(std::unordered_set<Key,Hash,KeyEqual,Allocator> & container,Predicate pred)353*635a8641SAndroid Build Coastguard Worker void EraseIf(std::unordered_set<Key, Hash, KeyEqual, Allocator>& container,
354*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
355*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
356*635a8641SAndroid Build Coastguard Worker }
357*635a8641SAndroid Build Coastguard Worker 
358*635a8641SAndroid Build Coastguard Worker template <class Key,
359*635a8641SAndroid Build Coastguard Worker           class Hash,
360*635a8641SAndroid Build Coastguard Worker           class KeyEqual,
361*635a8641SAndroid Build Coastguard Worker           class Allocator,
362*635a8641SAndroid Build Coastguard Worker           class Predicate>
EraseIf(std::unordered_multiset<Key,Hash,KeyEqual,Allocator> & container,Predicate pred)363*635a8641SAndroid Build Coastguard Worker void EraseIf(std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& container,
364*635a8641SAndroid Build Coastguard Worker              Predicate pred) {
365*635a8641SAndroid Build Coastguard Worker   internal::IterateAndEraseIf(container, pred);
366*635a8641SAndroid Build Coastguard Worker }
367*635a8641SAndroid Build Coastguard Worker 
368*635a8641SAndroid Build Coastguard Worker // A helper class to be used as the predicate with |EraseIf| to implement
369*635a8641SAndroid Build Coastguard Worker // in-place set intersection. Helps implement the algorithm of going through
370*635a8641SAndroid Build Coastguard Worker // each container an element at a time, erasing elements from the first
371*635a8641SAndroid Build Coastguard Worker // container if they aren't in the second container. Requires each container be
372*635a8641SAndroid Build Coastguard Worker // sorted. Note that the logic below appears inverted since it is returning
373*635a8641SAndroid Build Coastguard Worker // whether an element should be erased.
374*635a8641SAndroid Build Coastguard Worker template <class Collection>
375*635a8641SAndroid Build Coastguard Worker class IsNotIn {
376*635a8641SAndroid Build Coastguard Worker  public:
IsNotIn(const Collection & collection)377*635a8641SAndroid Build Coastguard Worker   explicit IsNotIn(const Collection& collection)
378*635a8641SAndroid Build Coastguard Worker       : i_(collection.begin()), end_(collection.end()) {}
379*635a8641SAndroid Build Coastguard Worker 
operator()380*635a8641SAndroid Build Coastguard Worker   bool operator()(const typename Collection::value_type& x) {
381*635a8641SAndroid Build Coastguard Worker     while (i_ != end_ && *i_ < x)
382*635a8641SAndroid Build Coastguard Worker       ++i_;
383*635a8641SAndroid Build Coastguard Worker     if (i_ == end_)
384*635a8641SAndroid Build Coastguard Worker       return true;
385*635a8641SAndroid Build Coastguard Worker     if (*i_ == x) {
386*635a8641SAndroid Build Coastguard Worker       ++i_;
387*635a8641SAndroid Build Coastguard Worker       return false;
388*635a8641SAndroid Build Coastguard Worker     }
389*635a8641SAndroid Build Coastguard Worker     return true;
390*635a8641SAndroid Build Coastguard Worker   }
391*635a8641SAndroid Build Coastguard Worker 
392*635a8641SAndroid Build Coastguard Worker  private:
393*635a8641SAndroid Build Coastguard Worker   typename Collection::const_iterator i_;
394*635a8641SAndroid Build Coastguard Worker   const typename Collection::const_iterator end_;
395*635a8641SAndroid Build Coastguard Worker };
396*635a8641SAndroid Build Coastguard Worker 
397*635a8641SAndroid Build Coastguard Worker // Helper for returning the optional value's address, or nullptr.
398*635a8641SAndroid Build Coastguard Worker template <class T>
OptionalOrNullptr(base::Optional<T> & optional)399*635a8641SAndroid Build Coastguard Worker T* OptionalOrNullptr(base::Optional<T>& optional) {
400*635a8641SAndroid Build Coastguard Worker   return optional.has_value() ? &optional.value() : nullptr;
401*635a8641SAndroid Build Coastguard Worker }
402*635a8641SAndroid Build Coastguard Worker 
403*635a8641SAndroid Build Coastguard Worker template <class T>
OptionalOrNullptr(const base::Optional<T> & optional)404*635a8641SAndroid Build Coastguard Worker const T* OptionalOrNullptr(const base::Optional<T>& optional) {
405*635a8641SAndroid Build Coastguard Worker   return optional.has_value() ? &optional.value() : nullptr;
406*635a8641SAndroid Build Coastguard Worker }
407*635a8641SAndroid Build Coastguard Worker 
408*635a8641SAndroid Build Coastguard Worker }  // namespace base
409*635a8641SAndroid Build Coastguard Worker 
410*635a8641SAndroid Build Coastguard Worker #endif  // BASE_STL_UTIL_H_
411