xref: /aosp_15_r20/external/libchrome/base/containers/small_map.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 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 #ifndef BASE_CONTAINERS_SMALL_MAP_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_CONTAINERS_SMALL_MAP_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <map>
11*635a8641SAndroid Build Coastguard Worker #include <new>
12*635a8641SAndroid Build Coastguard Worker #include <string>
13*635a8641SAndroid Build Coastguard Worker #include <utility>
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #include "base/containers/hash_tables.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker namespace base {
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker // small_map is a container with a std::map-like interface. It starts out
21*635a8641SAndroid Build Coastguard Worker // backed by a unsorted array but switches to some other container type if it
22*635a8641SAndroid Build Coastguard Worker // grows beyond this fixed size.
23*635a8641SAndroid Build Coastguard Worker //
24*635a8641SAndroid Build Coastguard Worker // Please see //base/containers/README.md for an overview of which container
25*635a8641SAndroid Build Coastguard Worker // to select.
26*635a8641SAndroid Build Coastguard Worker //
27*635a8641SAndroid Build Coastguard Worker // PROS
28*635a8641SAndroid Build Coastguard Worker //
29*635a8641SAndroid Build Coastguard Worker //  - Good memory locality and low overhead for smaller maps.
30*635a8641SAndroid Build Coastguard Worker //  - Handles large maps without the degenerate performance of flat_map.
31*635a8641SAndroid Build Coastguard Worker //
32*635a8641SAndroid Build Coastguard Worker // CONS
33*635a8641SAndroid Build Coastguard Worker //
34*635a8641SAndroid Build Coastguard Worker //  - Larger code size than the alternatives.
35*635a8641SAndroid Build Coastguard Worker //
36*635a8641SAndroid Build Coastguard Worker // IMPORTANT NOTES
37*635a8641SAndroid Build Coastguard Worker //
38*635a8641SAndroid Build Coastguard Worker //  - Iterators are invalidated across mutations.
39*635a8641SAndroid Build Coastguard Worker //
40*635a8641SAndroid Build Coastguard Worker // DETAILS
41*635a8641SAndroid Build Coastguard Worker //
42*635a8641SAndroid Build Coastguard Worker // base::small_map will pick up the comparator from the underlying map type. In
43*635a8641SAndroid Build Coastguard Worker // std::map only a "less" operator is defined, which requires us to do two
44*635a8641SAndroid Build Coastguard Worker // comparisons per element when doing the brute-force search in the simple
45*635a8641SAndroid Build Coastguard Worker // array. std::unordered_map has a key_equal function which will be used.
46*635a8641SAndroid Build Coastguard Worker //
47*635a8641SAndroid Build Coastguard Worker // We define default overrides for the common map types to avoid this
48*635a8641SAndroid Build Coastguard Worker // double-compare, but you should be aware of this if you use your own
49*635a8641SAndroid Build Coastguard Worker // operator< for your map and supply yor own version of == to the small_map.
50*635a8641SAndroid Build Coastguard Worker // You can use regular operator== by just doing:
51*635a8641SAndroid Build Coastguard Worker //
52*635a8641SAndroid Build Coastguard Worker //   base::small_map<std::map<MyKey, MyValue>, 4, std::equal_to<KyKey>>
53*635a8641SAndroid Build Coastguard Worker //
54*635a8641SAndroid Build Coastguard Worker //
55*635a8641SAndroid Build Coastguard Worker // USAGE
56*635a8641SAndroid Build Coastguard Worker // -----
57*635a8641SAndroid Build Coastguard Worker //
58*635a8641SAndroid Build Coastguard Worker // NormalMap:  The map type to fall back to.  This also defines the key
59*635a8641SAndroid Build Coastguard Worker //             and value types for the small_map.
60*635a8641SAndroid Build Coastguard Worker // kArraySize:  The size of the initial array of results. This will be
61*635a8641SAndroid Build Coastguard Worker //              allocated with the small_map object rather than separately on
62*635a8641SAndroid Build Coastguard Worker //              the heap. Once the map grows beyond this size, the map type
63*635a8641SAndroid Build Coastguard Worker //              will be used instead.
64*635a8641SAndroid Build Coastguard Worker // EqualKey:  A functor which tests two keys for equality.  If the wrapped
65*635a8641SAndroid Build Coastguard Worker //            map type has a "key_equal" member (hash_map does), then that will
66*635a8641SAndroid Build Coastguard Worker //            be used by default. If the wrapped map type has a strict weak
67*635a8641SAndroid Build Coastguard Worker //            ordering "key_compare" (std::map does), that will be used to
68*635a8641SAndroid Build Coastguard Worker //            implement equality by default.
69*635a8641SAndroid Build Coastguard Worker // MapInit: A functor that takes a NormalMap* and uses it to initialize the map.
70*635a8641SAndroid Build Coastguard Worker //          This functor will be called at most once per small_map, when the map
71*635a8641SAndroid Build Coastguard Worker //          exceeds the threshold of kArraySize and we are about to copy values
72*635a8641SAndroid Build Coastguard Worker //          from the array to the map. The functor *must* initialize the
73*635a8641SAndroid Build Coastguard Worker //          NormalMap* argument with placement new, since after it runs we
74*635a8641SAndroid Build Coastguard Worker //          assume that the NormalMap has been initialized.
75*635a8641SAndroid Build Coastguard Worker //
76*635a8641SAndroid Build Coastguard Worker // example:
77*635a8641SAndroid Build Coastguard Worker //   base::small_map<std::map<string, int>> days;
78*635a8641SAndroid Build Coastguard Worker //   days["sunday"   ] = 0;
79*635a8641SAndroid Build Coastguard Worker //   days["monday"   ] = 1;
80*635a8641SAndroid Build Coastguard Worker //   days["tuesday"  ] = 2;
81*635a8641SAndroid Build Coastguard Worker //   days["wednesday"] = 3;
82*635a8641SAndroid Build Coastguard Worker //   days["thursday" ] = 4;
83*635a8641SAndroid Build Coastguard Worker //   days["friday"   ] = 5;
84*635a8641SAndroid Build Coastguard Worker //   days["saturday" ] = 6;
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker namespace internal {
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker template <typename NormalMap>
89*635a8641SAndroid Build Coastguard Worker class small_map_default_init {
90*635a8641SAndroid Build Coastguard Worker  public:
operator()91*635a8641SAndroid Build Coastguard Worker   void operator()(NormalMap* map) const { new (map) NormalMap(); }
92*635a8641SAndroid Build Coastguard Worker };
93*635a8641SAndroid Build Coastguard Worker 
94*635a8641SAndroid Build Coastguard Worker // has_key_equal<M>::value is true iff there exists a type M::key_equal. This is
95*635a8641SAndroid Build Coastguard Worker // used to dispatch to one of the select_equal_key<> metafunctions below.
96*635a8641SAndroid Build Coastguard Worker template <typename M>
97*635a8641SAndroid Build Coastguard Worker struct has_key_equal {
98*635a8641SAndroid Build Coastguard Worker   typedef char sml;  // "small" is sometimes #defined so we use an abbreviation.
99*635a8641SAndroid Build Coastguard Worker   typedef struct { char dummy[2]; } big;
100*635a8641SAndroid Build Coastguard Worker   // Two functions, one accepts types that have a key_equal member, and one that
101*635a8641SAndroid Build Coastguard Worker   // accepts anything. They each return a value of a different size, so we can
102*635a8641SAndroid Build Coastguard Worker   // determine at compile-time which function would have been called.
103*635a8641SAndroid Build Coastguard Worker   template <typename U> static big test(typename U::key_equal*);
104*635a8641SAndroid Build Coastguard Worker   template <typename> static sml test(...);
105*635a8641SAndroid Build Coastguard Worker   // Determines if M::key_equal exists by looking at the size of the return
106*635a8641SAndroid Build Coastguard Worker   // type of the compiler-chosen test() function.
107*635a8641SAndroid Build Coastguard Worker   static const bool value = (sizeof(test<M>(0)) == sizeof(big));
108*635a8641SAndroid Build Coastguard Worker };
109*635a8641SAndroid Build Coastguard Worker template <typename M> const bool has_key_equal<M>::value;
110*635a8641SAndroid Build Coastguard Worker 
111*635a8641SAndroid Build Coastguard Worker // Base template used for map types that do NOT have an M::key_equal member,
112*635a8641SAndroid Build Coastguard Worker // e.g., std::map<>. These maps have a strict weak ordering comparator rather
113*635a8641SAndroid Build Coastguard Worker // than an equality functor, so equality will be implemented in terms of that
114*635a8641SAndroid Build Coastguard Worker // comparator.
115*635a8641SAndroid Build Coastguard Worker //
116*635a8641SAndroid Build Coastguard Worker // There's a partial specialization of this template below for map types that do
117*635a8641SAndroid Build Coastguard Worker // have an M::key_equal member.
118*635a8641SAndroid Build Coastguard Worker template <typename M, bool has_key_equal_value>
119*635a8641SAndroid Build Coastguard Worker struct select_equal_key {
120*635a8641SAndroid Build Coastguard Worker   struct equal_key {
operatorselect_equal_key::equal_key121*635a8641SAndroid Build Coastguard Worker     bool operator()(const typename M::key_type& left,
122*635a8641SAndroid Build Coastguard Worker                     const typename M::key_type& right) {
123*635a8641SAndroid Build Coastguard Worker       // Implements equality in terms of a strict weak ordering comparator.
124*635a8641SAndroid Build Coastguard Worker       typename M::key_compare comp;
125*635a8641SAndroid Build Coastguard Worker       return !comp(left, right) && !comp(right, left);
126*635a8641SAndroid Build Coastguard Worker     }
127*635a8641SAndroid Build Coastguard Worker   };
128*635a8641SAndroid Build Coastguard Worker };
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker // Provide overrides to use operator== for key compare for the "normal" map and
131*635a8641SAndroid Build Coastguard Worker // hash map types. If you override the default comparator or allocator for a
132*635a8641SAndroid Build Coastguard Worker // map or hash_map, or use another type of map, this won't get used.
133*635a8641SAndroid Build Coastguard Worker //
134*635a8641SAndroid Build Coastguard Worker // If we switch to using std::unordered_map for base::hash_map, then the
135*635a8641SAndroid Build Coastguard Worker // hash_map specialization can be removed.
136*635a8641SAndroid Build Coastguard Worker template <typename KeyType, typename ValueType>
137*635a8641SAndroid Build Coastguard Worker struct select_equal_key<std::map<KeyType, ValueType>, false> {
138*635a8641SAndroid Build Coastguard Worker   struct equal_key {
139*635a8641SAndroid Build Coastguard Worker     bool operator()(const KeyType& left, const KeyType& right) {
140*635a8641SAndroid Build Coastguard Worker       return left == right;
141*635a8641SAndroid Build Coastguard Worker     }
142*635a8641SAndroid Build Coastguard Worker   };
143*635a8641SAndroid Build Coastguard Worker };
144*635a8641SAndroid Build Coastguard Worker template <typename KeyType, typename ValueType>
145*635a8641SAndroid Build Coastguard Worker struct select_equal_key<base::hash_map<KeyType, ValueType>, false> {
146*635a8641SAndroid Build Coastguard Worker   struct equal_key {
147*635a8641SAndroid Build Coastguard Worker     bool operator()(const KeyType& left, const KeyType& right) {
148*635a8641SAndroid Build Coastguard Worker       return left == right;
149*635a8641SAndroid Build Coastguard Worker     }
150*635a8641SAndroid Build Coastguard Worker   };
151*635a8641SAndroid Build Coastguard Worker };
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker // Partial template specialization handles case where M::key_equal exists, e.g.,
154*635a8641SAndroid Build Coastguard Worker // hash_map<>.
155*635a8641SAndroid Build Coastguard Worker template <typename M>
156*635a8641SAndroid Build Coastguard Worker struct select_equal_key<M, true> {
157*635a8641SAndroid Build Coastguard Worker   typedef typename M::key_equal equal_key;
158*635a8641SAndroid Build Coastguard Worker };
159*635a8641SAndroid Build Coastguard Worker 
160*635a8641SAndroid Build Coastguard Worker }  // namespace internal
161*635a8641SAndroid Build Coastguard Worker 
162*635a8641SAndroid Build Coastguard Worker template <typename NormalMap,
163*635a8641SAndroid Build Coastguard Worker           int kArraySize = 4,
164*635a8641SAndroid Build Coastguard Worker           typename EqualKey = typename internal::select_equal_key<
165*635a8641SAndroid Build Coastguard Worker               NormalMap,
166*635a8641SAndroid Build Coastguard Worker               internal::has_key_equal<NormalMap>::value>::equal_key,
167*635a8641SAndroid Build Coastguard Worker           typename MapInit = internal::small_map_default_init<NormalMap>>
168*635a8641SAndroid Build Coastguard Worker class small_map {
169*635a8641SAndroid Build Coastguard Worker   // We cannot rely on the compiler to reject array of size 0.  In
170*635a8641SAndroid Build Coastguard Worker   // particular, gcc 2.95.3 does it but later versions allow 0-length
171*635a8641SAndroid Build Coastguard Worker   // arrays.  Therefore, we explicitly reject non-positive kArraySize
172*635a8641SAndroid Build Coastguard Worker   // here.
173*635a8641SAndroid Build Coastguard Worker   static_assert(kArraySize > 0, "default initial size should be positive");
174*635a8641SAndroid Build Coastguard Worker 
175*635a8641SAndroid Build Coastguard Worker  public:
176*635a8641SAndroid Build Coastguard Worker   typedef typename NormalMap::key_type key_type;
177*635a8641SAndroid Build Coastguard Worker   typedef typename NormalMap::mapped_type data_type;
178*635a8641SAndroid Build Coastguard Worker   typedef typename NormalMap::mapped_type mapped_type;
179*635a8641SAndroid Build Coastguard Worker   typedef typename NormalMap::value_type value_type;
180*635a8641SAndroid Build Coastguard Worker   typedef EqualKey key_equal;
181*635a8641SAndroid Build Coastguard Worker 
182*635a8641SAndroid Build Coastguard Worker   small_map() : size_(0), functor_(MapInit()) {}
183*635a8641SAndroid Build Coastguard Worker 
184*635a8641SAndroid Build Coastguard Worker   explicit small_map(const MapInit& functor) : size_(0), functor_(functor) {}
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker   // Allow copy-constructor and assignment, since STL allows them too.
187*635a8641SAndroid Build Coastguard Worker   small_map(const small_map& src) {
188*635a8641SAndroid Build Coastguard Worker     // size_ and functor_ are initted in InitFrom()
189*635a8641SAndroid Build Coastguard Worker     InitFrom(src);
190*635a8641SAndroid Build Coastguard Worker   }
191*635a8641SAndroid Build Coastguard Worker   void operator=(const small_map& src) {
192*635a8641SAndroid Build Coastguard Worker     if (&src == this) return;
193*635a8641SAndroid Build Coastguard Worker 
194*635a8641SAndroid Build Coastguard Worker     // This is not optimal. If src and dest are both using the small
195*635a8641SAndroid Build Coastguard Worker     // array, we could skip the teardown and reconstruct. One problem
196*635a8641SAndroid Build Coastguard Worker     // to be resolved is that the value_type itself is pair<const K,
197*635a8641SAndroid Build Coastguard Worker     // V>, and const K is not assignable.
198*635a8641SAndroid Build Coastguard Worker     Destroy();
199*635a8641SAndroid Build Coastguard Worker     InitFrom(src);
200*635a8641SAndroid Build Coastguard Worker   }
201*635a8641SAndroid Build Coastguard Worker   ~small_map() { Destroy(); }
202*635a8641SAndroid Build Coastguard Worker 
203*635a8641SAndroid Build Coastguard Worker   class const_iterator;
204*635a8641SAndroid Build Coastguard Worker 
205*635a8641SAndroid Build Coastguard Worker   class iterator {
206*635a8641SAndroid Build Coastguard Worker    public:
207*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::iterator::iterator_category iterator_category;
208*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::iterator::value_type value_type;
209*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::iterator::difference_type difference_type;
210*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::iterator::pointer pointer;
211*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::iterator::reference reference;
212*635a8641SAndroid Build Coastguard Worker 
213*635a8641SAndroid Build Coastguard Worker     inline iterator(): array_iter_(NULL) {}
214*635a8641SAndroid Build Coastguard Worker 
215*635a8641SAndroid Build Coastguard Worker     inline iterator& operator++() {
216*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
217*635a8641SAndroid Build Coastguard Worker         ++array_iter_;
218*635a8641SAndroid Build Coastguard Worker       } else {
219*635a8641SAndroid Build Coastguard Worker         ++hash_iter_;
220*635a8641SAndroid Build Coastguard Worker       }
221*635a8641SAndroid Build Coastguard Worker       return *this;
222*635a8641SAndroid Build Coastguard Worker     }
223*635a8641SAndroid Build Coastguard Worker     inline iterator operator++(int /*unused*/) {
224*635a8641SAndroid Build Coastguard Worker       iterator result(*this);
225*635a8641SAndroid Build Coastguard Worker       ++(*this);
226*635a8641SAndroid Build Coastguard Worker       return result;
227*635a8641SAndroid Build Coastguard Worker     }
228*635a8641SAndroid Build Coastguard Worker     inline iterator& operator--() {
229*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
230*635a8641SAndroid Build Coastguard Worker         --array_iter_;
231*635a8641SAndroid Build Coastguard Worker       } else {
232*635a8641SAndroid Build Coastguard Worker         --hash_iter_;
233*635a8641SAndroid Build Coastguard Worker       }
234*635a8641SAndroid Build Coastguard Worker       return *this;
235*635a8641SAndroid Build Coastguard Worker     }
236*635a8641SAndroid Build Coastguard Worker     inline iterator operator--(int /*unused*/) {
237*635a8641SAndroid Build Coastguard Worker       iterator result(*this);
238*635a8641SAndroid Build Coastguard Worker       --(*this);
239*635a8641SAndroid Build Coastguard Worker       return result;
240*635a8641SAndroid Build Coastguard Worker     }
241*635a8641SAndroid Build Coastguard Worker     inline value_type* operator->() const {
242*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
243*635a8641SAndroid Build Coastguard Worker         return array_iter_;
244*635a8641SAndroid Build Coastguard Worker       } else {
245*635a8641SAndroid Build Coastguard Worker         return hash_iter_.operator->();
246*635a8641SAndroid Build Coastguard Worker       }
247*635a8641SAndroid Build Coastguard Worker     }
248*635a8641SAndroid Build Coastguard Worker 
249*635a8641SAndroid Build Coastguard Worker     inline value_type& operator*() const {
250*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
251*635a8641SAndroid Build Coastguard Worker         return *array_iter_;
252*635a8641SAndroid Build Coastguard Worker       } else {
253*635a8641SAndroid Build Coastguard Worker         return *hash_iter_;
254*635a8641SAndroid Build Coastguard Worker       }
255*635a8641SAndroid Build Coastguard Worker     }
256*635a8641SAndroid Build Coastguard Worker 
257*635a8641SAndroid Build Coastguard Worker     inline bool operator==(const iterator& other) const {
258*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
259*635a8641SAndroid Build Coastguard Worker         return array_iter_ == other.array_iter_;
260*635a8641SAndroid Build Coastguard Worker       } else {
261*635a8641SAndroid Build Coastguard Worker         return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
262*635a8641SAndroid Build Coastguard Worker       }
263*635a8641SAndroid Build Coastguard Worker     }
264*635a8641SAndroid Build Coastguard Worker 
265*635a8641SAndroid Build Coastguard Worker     inline bool operator!=(const iterator& other) const {
266*635a8641SAndroid Build Coastguard Worker       return !(*this == other);
267*635a8641SAndroid Build Coastguard Worker     }
268*635a8641SAndroid Build Coastguard Worker 
269*635a8641SAndroid Build Coastguard Worker     bool operator==(const const_iterator& other) const;
270*635a8641SAndroid Build Coastguard Worker     bool operator!=(const const_iterator& other) const;
271*635a8641SAndroid Build Coastguard Worker 
272*635a8641SAndroid Build Coastguard Worker    private:
273*635a8641SAndroid Build Coastguard Worker     friend class small_map;
274*635a8641SAndroid Build Coastguard Worker     friend class const_iterator;
275*635a8641SAndroid Build Coastguard Worker     inline explicit iterator(value_type* init) : array_iter_(init) {}
276*635a8641SAndroid Build Coastguard Worker     inline explicit iterator(const typename NormalMap::iterator& init)
277*635a8641SAndroid Build Coastguard Worker       : array_iter_(NULL), hash_iter_(init) {}
278*635a8641SAndroid Build Coastguard Worker 
279*635a8641SAndroid Build Coastguard Worker     value_type* array_iter_;
280*635a8641SAndroid Build Coastguard Worker     typename NormalMap::iterator hash_iter_;
281*635a8641SAndroid Build Coastguard Worker   };
282*635a8641SAndroid Build Coastguard Worker 
283*635a8641SAndroid Build Coastguard Worker   class const_iterator {
284*635a8641SAndroid Build Coastguard Worker    public:
285*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::const_iterator::iterator_category
286*635a8641SAndroid Build Coastguard Worker         iterator_category;
287*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::const_iterator::value_type value_type;
288*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::const_iterator::difference_type difference_type;
289*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::const_iterator::pointer pointer;
290*635a8641SAndroid Build Coastguard Worker     typedef typename NormalMap::const_iterator::reference reference;
291*635a8641SAndroid Build Coastguard Worker 
292*635a8641SAndroid Build Coastguard Worker     inline const_iterator(): array_iter_(NULL) {}
293*635a8641SAndroid Build Coastguard Worker     // Non-explicit ctor lets us convert regular iterators to const iterators
294*635a8641SAndroid Build Coastguard Worker     inline const_iterator(const iterator& other)
295*635a8641SAndroid Build Coastguard Worker       : array_iter_(other.array_iter_), hash_iter_(other.hash_iter_) {}
296*635a8641SAndroid Build Coastguard Worker 
297*635a8641SAndroid Build Coastguard Worker     inline const_iterator& operator++() {
298*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
299*635a8641SAndroid Build Coastguard Worker         ++array_iter_;
300*635a8641SAndroid Build Coastguard Worker       } else {
301*635a8641SAndroid Build Coastguard Worker         ++hash_iter_;
302*635a8641SAndroid Build Coastguard Worker       }
303*635a8641SAndroid Build Coastguard Worker       return *this;
304*635a8641SAndroid Build Coastguard Worker     }
305*635a8641SAndroid Build Coastguard Worker     inline const_iterator operator++(int /*unused*/) {
306*635a8641SAndroid Build Coastguard Worker       const_iterator result(*this);
307*635a8641SAndroid Build Coastguard Worker       ++(*this);
308*635a8641SAndroid Build Coastguard Worker       return result;
309*635a8641SAndroid Build Coastguard Worker     }
310*635a8641SAndroid Build Coastguard Worker 
311*635a8641SAndroid Build Coastguard Worker     inline const_iterator& operator--() {
312*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
313*635a8641SAndroid Build Coastguard Worker         --array_iter_;
314*635a8641SAndroid Build Coastguard Worker       } else {
315*635a8641SAndroid Build Coastguard Worker         --hash_iter_;
316*635a8641SAndroid Build Coastguard Worker       }
317*635a8641SAndroid Build Coastguard Worker       return *this;
318*635a8641SAndroid Build Coastguard Worker     }
319*635a8641SAndroid Build Coastguard Worker     inline const_iterator operator--(int /*unused*/) {
320*635a8641SAndroid Build Coastguard Worker       const_iterator result(*this);
321*635a8641SAndroid Build Coastguard Worker       --(*this);
322*635a8641SAndroid Build Coastguard Worker       return result;
323*635a8641SAndroid Build Coastguard Worker     }
324*635a8641SAndroid Build Coastguard Worker 
325*635a8641SAndroid Build Coastguard Worker     inline const value_type* operator->() const {
326*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
327*635a8641SAndroid Build Coastguard Worker         return array_iter_;
328*635a8641SAndroid Build Coastguard Worker       } else {
329*635a8641SAndroid Build Coastguard Worker         return hash_iter_.operator->();
330*635a8641SAndroid Build Coastguard Worker       }
331*635a8641SAndroid Build Coastguard Worker     }
332*635a8641SAndroid Build Coastguard Worker 
333*635a8641SAndroid Build Coastguard Worker     inline const value_type& operator*() const {
334*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
335*635a8641SAndroid Build Coastguard Worker         return *array_iter_;
336*635a8641SAndroid Build Coastguard Worker       } else {
337*635a8641SAndroid Build Coastguard Worker         return *hash_iter_;
338*635a8641SAndroid Build Coastguard Worker       }
339*635a8641SAndroid Build Coastguard Worker     }
340*635a8641SAndroid Build Coastguard Worker 
341*635a8641SAndroid Build Coastguard Worker     inline bool operator==(const const_iterator& other) const {
342*635a8641SAndroid Build Coastguard Worker       if (array_iter_ != NULL) {
343*635a8641SAndroid Build Coastguard Worker         return array_iter_ == other.array_iter_;
344*635a8641SAndroid Build Coastguard Worker       } else {
345*635a8641SAndroid Build Coastguard Worker         return other.array_iter_ == NULL && hash_iter_ == other.hash_iter_;
346*635a8641SAndroid Build Coastguard Worker       }
347*635a8641SAndroid Build Coastguard Worker     }
348*635a8641SAndroid Build Coastguard Worker 
349*635a8641SAndroid Build Coastguard Worker     inline bool operator!=(const const_iterator& other) const {
350*635a8641SAndroid Build Coastguard Worker       return !(*this == other);
351*635a8641SAndroid Build Coastguard Worker     }
352*635a8641SAndroid Build Coastguard Worker 
353*635a8641SAndroid Build Coastguard Worker    private:
354*635a8641SAndroid Build Coastguard Worker     friend class small_map;
355*635a8641SAndroid Build Coastguard Worker     inline explicit const_iterator(const value_type* init)
356*635a8641SAndroid Build Coastguard Worker         : array_iter_(init) {}
357*635a8641SAndroid Build Coastguard Worker     inline explicit const_iterator(
358*635a8641SAndroid Build Coastguard Worker         const typename NormalMap::const_iterator& init)
359*635a8641SAndroid Build Coastguard Worker       : array_iter_(NULL), hash_iter_(init) {}
360*635a8641SAndroid Build Coastguard Worker 
361*635a8641SAndroid Build Coastguard Worker     const value_type* array_iter_;
362*635a8641SAndroid Build Coastguard Worker     typename NormalMap::const_iterator hash_iter_;
363*635a8641SAndroid Build Coastguard Worker   };
364*635a8641SAndroid Build Coastguard Worker 
365*635a8641SAndroid Build Coastguard Worker   iterator find(const key_type& key) {
366*635a8641SAndroid Build Coastguard Worker     key_equal compare;
367*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
368*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
369*635a8641SAndroid Build Coastguard Worker         if (compare(array_[i].first, key)) {
370*635a8641SAndroid Build Coastguard Worker           return iterator(array_ + i);
371*635a8641SAndroid Build Coastguard Worker         }
372*635a8641SAndroid Build Coastguard Worker       }
373*635a8641SAndroid Build Coastguard Worker       return iterator(array_ + size_);
374*635a8641SAndroid Build Coastguard Worker     } else {
375*635a8641SAndroid Build Coastguard Worker       return iterator(map()->find(key));
376*635a8641SAndroid Build Coastguard Worker     }
377*635a8641SAndroid Build Coastguard Worker   }
378*635a8641SAndroid Build Coastguard Worker 
379*635a8641SAndroid Build Coastguard Worker   const_iterator find(const key_type& key) const {
380*635a8641SAndroid Build Coastguard Worker     key_equal compare;
381*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
382*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
383*635a8641SAndroid Build Coastguard Worker         if (compare(array_[i].first, key)) {
384*635a8641SAndroid Build Coastguard Worker           return const_iterator(array_ + i);
385*635a8641SAndroid Build Coastguard Worker         }
386*635a8641SAndroid Build Coastguard Worker       }
387*635a8641SAndroid Build Coastguard Worker       return const_iterator(array_ + size_);
388*635a8641SAndroid Build Coastguard Worker     } else {
389*635a8641SAndroid Build Coastguard Worker       return const_iterator(map()->find(key));
390*635a8641SAndroid Build Coastguard Worker     }
391*635a8641SAndroid Build Coastguard Worker   }
392*635a8641SAndroid Build Coastguard Worker 
393*635a8641SAndroid Build Coastguard Worker   // Invalidates iterators.
394*635a8641SAndroid Build Coastguard Worker   data_type& operator[](const key_type& key) {
395*635a8641SAndroid Build Coastguard Worker     key_equal compare;
396*635a8641SAndroid Build Coastguard Worker 
397*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
398*635a8641SAndroid Build Coastguard Worker       // operator[] searches backwards, favoring recently-added
399*635a8641SAndroid Build Coastguard Worker       // elements.
400*635a8641SAndroid Build Coastguard Worker       for (int i = size_-1; i >= 0; --i) {
401*635a8641SAndroid Build Coastguard Worker         if (compare(array_[i].first, key)) {
402*635a8641SAndroid Build Coastguard Worker           return array_[i].second;
403*635a8641SAndroid Build Coastguard Worker         }
404*635a8641SAndroid Build Coastguard Worker       }
405*635a8641SAndroid Build Coastguard Worker       if (size_ == kArraySize) {
406*635a8641SAndroid Build Coastguard Worker         ConvertToRealMap();
407*635a8641SAndroid Build Coastguard Worker         return map_[key];
408*635a8641SAndroid Build Coastguard Worker       } else {
409*635a8641SAndroid Build Coastguard Worker         new (&array_[size_]) value_type(key, data_type());
410*635a8641SAndroid Build Coastguard Worker         return array_[size_++].second;
411*635a8641SAndroid Build Coastguard Worker       }
412*635a8641SAndroid Build Coastguard Worker     } else {
413*635a8641SAndroid Build Coastguard Worker       return map_[key];
414*635a8641SAndroid Build Coastguard Worker     }
415*635a8641SAndroid Build Coastguard Worker   }
416*635a8641SAndroid Build Coastguard Worker 
417*635a8641SAndroid Build Coastguard Worker   // Invalidates iterators.
418*635a8641SAndroid Build Coastguard Worker   std::pair<iterator, bool> insert(const value_type& x) {
419*635a8641SAndroid Build Coastguard Worker     key_equal compare;
420*635a8641SAndroid Build Coastguard Worker 
421*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
422*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
423*635a8641SAndroid Build Coastguard Worker         if (compare(array_[i].first, x.first)) {
424*635a8641SAndroid Build Coastguard Worker           return std::make_pair(iterator(array_ + i), false);
425*635a8641SAndroid Build Coastguard Worker         }
426*635a8641SAndroid Build Coastguard Worker       }
427*635a8641SAndroid Build Coastguard Worker       if (size_ == kArraySize) {
428*635a8641SAndroid Build Coastguard Worker         ConvertToRealMap();  // Invalidates all iterators!
429*635a8641SAndroid Build Coastguard Worker         std::pair<typename NormalMap::iterator, bool> ret = map_.insert(x);
430*635a8641SAndroid Build Coastguard Worker         return std::make_pair(iterator(ret.first), ret.second);
431*635a8641SAndroid Build Coastguard Worker       } else {
432*635a8641SAndroid Build Coastguard Worker         new (&array_[size_]) value_type(x);
433*635a8641SAndroid Build Coastguard Worker         return std::make_pair(iterator(array_ + size_++), true);
434*635a8641SAndroid Build Coastguard Worker       }
435*635a8641SAndroid Build Coastguard Worker     } else {
436*635a8641SAndroid Build Coastguard Worker       std::pair<typename NormalMap::iterator, bool> ret = map_.insert(x);
437*635a8641SAndroid Build Coastguard Worker       return std::make_pair(iterator(ret.first), ret.second);
438*635a8641SAndroid Build Coastguard Worker     }
439*635a8641SAndroid Build Coastguard Worker   }
440*635a8641SAndroid Build Coastguard Worker 
441*635a8641SAndroid Build Coastguard Worker   // Invalidates iterators.
442*635a8641SAndroid Build Coastguard Worker   template <class InputIterator>
443*635a8641SAndroid Build Coastguard Worker   void insert(InputIterator f, InputIterator l) {
444*635a8641SAndroid Build Coastguard Worker     while (f != l) {
445*635a8641SAndroid Build Coastguard Worker       insert(*f);
446*635a8641SAndroid Build Coastguard Worker       ++f;
447*635a8641SAndroid Build Coastguard Worker     }
448*635a8641SAndroid Build Coastguard Worker   }
449*635a8641SAndroid Build Coastguard Worker 
450*635a8641SAndroid Build Coastguard Worker   // Invalidates iterators.
451*635a8641SAndroid Build Coastguard Worker   template <typename... Args>
452*635a8641SAndroid Build Coastguard Worker   std::pair<iterator, bool> emplace(Args&&... args) {
453*635a8641SAndroid Build Coastguard Worker     key_equal compare;
454*635a8641SAndroid Build Coastguard Worker 
455*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
456*635a8641SAndroid Build Coastguard Worker       value_type x(std::forward<Args>(args)...);
457*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
458*635a8641SAndroid Build Coastguard Worker         if (compare(array_[i].first, x.first)) {
459*635a8641SAndroid Build Coastguard Worker           return std::make_pair(iterator(array_ + i), false);
460*635a8641SAndroid Build Coastguard Worker         }
461*635a8641SAndroid Build Coastguard Worker       }
462*635a8641SAndroid Build Coastguard Worker       if (size_ == kArraySize) {
463*635a8641SAndroid Build Coastguard Worker         ConvertToRealMap();  // Invalidates all iterators!
464*635a8641SAndroid Build Coastguard Worker         std::pair<typename NormalMap::iterator, bool> ret =
465*635a8641SAndroid Build Coastguard Worker             map_.emplace(std::move(x));
466*635a8641SAndroid Build Coastguard Worker         return std::make_pair(iterator(ret.first), ret.second);
467*635a8641SAndroid Build Coastguard Worker       } else {
468*635a8641SAndroid Build Coastguard Worker         new (&array_[size_]) value_type(std::move(x));
469*635a8641SAndroid Build Coastguard Worker         return std::make_pair(iterator(array_ + size_++), true);
470*635a8641SAndroid Build Coastguard Worker       }
471*635a8641SAndroid Build Coastguard Worker     } else {
472*635a8641SAndroid Build Coastguard Worker       std::pair<typename NormalMap::iterator, bool> ret =
473*635a8641SAndroid Build Coastguard Worker           map_.emplace(std::forward<Args>(args)...);
474*635a8641SAndroid Build Coastguard Worker       return std::make_pair(iterator(ret.first), ret.second);
475*635a8641SAndroid Build Coastguard Worker     }
476*635a8641SAndroid Build Coastguard Worker   }
477*635a8641SAndroid Build Coastguard Worker 
478*635a8641SAndroid Build Coastguard Worker   iterator begin() {
479*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
480*635a8641SAndroid Build Coastguard Worker       return iterator(array_);
481*635a8641SAndroid Build Coastguard Worker     } else {
482*635a8641SAndroid Build Coastguard Worker       return iterator(map_.begin());
483*635a8641SAndroid Build Coastguard Worker     }
484*635a8641SAndroid Build Coastguard Worker   }
485*635a8641SAndroid Build Coastguard Worker   const_iterator begin() const {
486*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
487*635a8641SAndroid Build Coastguard Worker       return const_iterator(array_);
488*635a8641SAndroid Build Coastguard Worker     } else {
489*635a8641SAndroid Build Coastguard Worker       return const_iterator(map_.begin());
490*635a8641SAndroid Build Coastguard Worker     }
491*635a8641SAndroid Build Coastguard Worker   }
492*635a8641SAndroid Build Coastguard Worker 
493*635a8641SAndroid Build Coastguard Worker   iterator end() {
494*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
495*635a8641SAndroid Build Coastguard Worker       return iterator(array_ + size_);
496*635a8641SAndroid Build Coastguard Worker     } else {
497*635a8641SAndroid Build Coastguard Worker       return iterator(map_.end());
498*635a8641SAndroid Build Coastguard Worker     }
499*635a8641SAndroid Build Coastguard Worker   }
500*635a8641SAndroid Build Coastguard Worker   const_iterator end() const {
501*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
502*635a8641SAndroid Build Coastguard Worker       return const_iterator(array_ + size_);
503*635a8641SAndroid Build Coastguard Worker     } else {
504*635a8641SAndroid Build Coastguard Worker       return const_iterator(map_.end());
505*635a8641SAndroid Build Coastguard Worker     }
506*635a8641SAndroid Build Coastguard Worker   }
507*635a8641SAndroid Build Coastguard Worker 
508*635a8641SAndroid Build Coastguard Worker   void clear() {
509*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
510*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
511*635a8641SAndroid Build Coastguard Worker         array_[i].~value_type();
512*635a8641SAndroid Build Coastguard Worker       }
513*635a8641SAndroid Build Coastguard Worker     } else {
514*635a8641SAndroid Build Coastguard Worker       map_.~NormalMap();
515*635a8641SAndroid Build Coastguard Worker     }
516*635a8641SAndroid Build Coastguard Worker     size_ = 0;
517*635a8641SAndroid Build Coastguard Worker   }
518*635a8641SAndroid Build Coastguard Worker 
519*635a8641SAndroid Build Coastguard Worker   // Invalidates iterators. Returns iterator following the last removed element.
520*635a8641SAndroid Build Coastguard Worker   iterator erase(const iterator& position) {
521*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
522*635a8641SAndroid Build Coastguard Worker       int i = position.array_iter_ - array_;
523*635a8641SAndroid Build Coastguard Worker       array_[i].~value_type();
524*635a8641SAndroid Build Coastguard Worker       --size_;
525*635a8641SAndroid Build Coastguard Worker       if (i != size_) {
526*635a8641SAndroid Build Coastguard Worker         new (&array_[i]) value_type(std::move(array_[size_]));
527*635a8641SAndroid Build Coastguard Worker         array_[size_].~value_type();
528*635a8641SAndroid Build Coastguard Worker         return iterator(array_ + i);
529*635a8641SAndroid Build Coastguard Worker       }
530*635a8641SAndroid Build Coastguard Worker       return end();
531*635a8641SAndroid Build Coastguard Worker     }
532*635a8641SAndroid Build Coastguard Worker     return iterator(map_.erase(position.hash_iter_));
533*635a8641SAndroid Build Coastguard Worker   }
534*635a8641SAndroid Build Coastguard Worker 
535*635a8641SAndroid Build Coastguard Worker   size_t erase(const key_type& key) {
536*635a8641SAndroid Build Coastguard Worker     iterator iter = find(key);
537*635a8641SAndroid Build Coastguard Worker     if (iter == end()) return 0u;
538*635a8641SAndroid Build Coastguard Worker     erase(iter);
539*635a8641SAndroid Build Coastguard Worker     return 1u;
540*635a8641SAndroid Build Coastguard Worker   }
541*635a8641SAndroid Build Coastguard Worker 
542*635a8641SAndroid Build Coastguard Worker   size_t count(const key_type& key) const {
543*635a8641SAndroid Build Coastguard Worker     return (find(key) == end()) ? 0 : 1;
544*635a8641SAndroid Build Coastguard Worker   }
545*635a8641SAndroid Build Coastguard Worker 
546*635a8641SAndroid Build Coastguard Worker   size_t size() const {
547*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
548*635a8641SAndroid Build Coastguard Worker       return static_cast<size_t>(size_);
549*635a8641SAndroid Build Coastguard Worker     } else {
550*635a8641SAndroid Build Coastguard Worker       return map_.size();
551*635a8641SAndroid Build Coastguard Worker     }
552*635a8641SAndroid Build Coastguard Worker   }
553*635a8641SAndroid Build Coastguard Worker 
554*635a8641SAndroid Build Coastguard Worker   bool empty() const {
555*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
556*635a8641SAndroid Build Coastguard Worker       return (size_ == 0);
557*635a8641SAndroid Build Coastguard Worker     } else {
558*635a8641SAndroid Build Coastguard Worker       return map_.empty();
559*635a8641SAndroid Build Coastguard Worker     }
560*635a8641SAndroid Build Coastguard Worker   }
561*635a8641SAndroid Build Coastguard Worker 
562*635a8641SAndroid Build Coastguard Worker   // Returns true if we have fallen back to using the underlying map
563*635a8641SAndroid Build Coastguard Worker   // representation.
564*635a8641SAndroid Build Coastguard Worker   bool UsingFullMap() const {
565*635a8641SAndroid Build Coastguard Worker     return size_ < 0;
566*635a8641SAndroid Build Coastguard Worker   }
567*635a8641SAndroid Build Coastguard Worker 
568*635a8641SAndroid Build Coastguard Worker   inline NormalMap* map() {
569*635a8641SAndroid Build Coastguard Worker     CHECK(UsingFullMap());
570*635a8641SAndroid Build Coastguard Worker     return &map_;
571*635a8641SAndroid Build Coastguard Worker   }
572*635a8641SAndroid Build Coastguard Worker   inline const NormalMap* map() const {
573*635a8641SAndroid Build Coastguard Worker     CHECK(UsingFullMap());
574*635a8641SAndroid Build Coastguard Worker     return &map_;
575*635a8641SAndroid Build Coastguard Worker   }
576*635a8641SAndroid Build Coastguard Worker 
577*635a8641SAndroid Build Coastguard Worker  private:
578*635a8641SAndroid Build Coastguard Worker   int size_;  // negative = using hash_map
579*635a8641SAndroid Build Coastguard Worker 
580*635a8641SAndroid Build Coastguard Worker   MapInit functor_;
581*635a8641SAndroid Build Coastguard Worker 
582*635a8641SAndroid Build Coastguard Worker   // We want to call constructors and destructors manually, but we don't want to
583*635a8641SAndroid Build Coastguard Worker   // allocate and deallocate the memory used for them separately. Since array_
584*635a8641SAndroid Build Coastguard Worker   // and map_ are mutually exclusive, we'll put them in a union.
585*635a8641SAndroid Build Coastguard Worker   union {
586*635a8641SAndroid Build Coastguard Worker     value_type array_[kArraySize];
587*635a8641SAndroid Build Coastguard Worker     NormalMap map_;
588*635a8641SAndroid Build Coastguard Worker   };
589*635a8641SAndroid Build Coastguard Worker 
590*635a8641SAndroid Build Coastguard Worker   void ConvertToRealMap() {
591*635a8641SAndroid Build Coastguard Worker     // Storage for the elements in the temporary array. This is intentionally
592*635a8641SAndroid Build Coastguard Worker     // declared as a union to avoid having to default-construct |kArraySize|
593*635a8641SAndroid Build Coastguard Worker     // elements, only to move construct over them in the initial loop.
594*635a8641SAndroid Build Coastguard Worker     union Storage {
595*635a8641SAndroid Build Coastguard Worker       Storage() {}
596*635a8641SAndroid Build Coastguard Worker       ~Storage() {}
597*635a8641SAndroid Build Coastguard Worker       value_type array[kArraySize];
598*635a8641SAndroid Build Coastguard Worker     } temp;
599*635a8641SAndroid Build Coastguard Worker 
600*635a8641SAndroid Build Coastguard Worker     // Move the current elements into a temporary array.
601*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < kArraySize; i++) {
602*635a8641SAndroid Build Coastguard Worker       new (&temp.array[i]) value_type(std::move(array_[i]));
603*635a8641SAndroid Build Coastguard Worker       array_[i].~value_type();
604*635a8641SAndroid Build Coastguard Worker     }
605*635a8641SAndroid Build Coastguard Worker 
606*635a8641SAndroid Build Coastguard Worker     // Initialize the map.
607*635a8641SAndroid Build Coastguard Worker     size_ = -1;
608*635a8641SAndroid Build Coastguard Worker     functor_(&map_);
609*635a8641SAndroid Build Coastguard Worker 
610*635a8641SAndroid Build Coastguard Worker     // Insert elements into it.
611*635a8641SAndroid Build Coastguard Worker     for (int i = 0; i < kArraySize; i++) {
612*635a8641SAndroid Build Coastguard Worker       map_.insert(std::move(temp.array[i]));
613*635a8641SAndroid Build Coastguard Worker       temp.array[i].~value_type();
614*635a8641SAndroid Build Coastguard Worker     }
615*635a8641SAndroid Build Coastguard Worker   }
616*635a8641SAndroid Build Coastguard Worker 
617*635a8641SAndroid Build Coastguard Worker   // Helpers for constructors and destructors.
618*635a8641SAndroid Build Coastguard Worker   void InitFrom(const small_map& src) {
619*635a8641SAndroid Build Coastguard Worker     functor_ = src.functor_;
620*635a8641SAndroid Build Coastguard Worker     size_ = src.size_;
621*635a8641SAndroid Build Coastguard Worker     if (src.size_ >= 0) {
622*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
623*635a8641SAndroid Build Coastguard Worker         new (&array_[i]) value_type(src.array_[i]);
624*635a8641SAndroid Build Coastguard Worker       }
625*635a8641SAndroid Build Coastguard Worker     } else {
626*635a8641SAndroid Build Coastguard Worker       functor_(&map_);
627*635a8641SAndroid Build Coastguard Worker       map_ = src.map_;
628*635a8641SAndroid Build Coastguard Worker     }
629*635a8641SAndroid Build Coastguard Worker   }
630*635a8641SAndroid Build Coastguard Worker   void Destroy() {
631*635a8641SAndroid Build Coastguard Worker     if (size_ >= 0) {
632*635a8641SAndroid Build Coastguard Worker       for (int i = 0; i < size_; i++) {
633*635a8641SAndroid Build Coastguard Worker         array_[i].~value_type();
634*635a8641SAndroid Build Coastguard Worker       }
635*635a8641SAndroid Build Coastguard Worker     } else {
636*635a8641SAndroid Build Coastguard Worker       map_.~NormalMap();
637*635a8641SAndroid Build Coastguard Worker     }
638*635a8641SAndroid Build Coastguard Worker   }
639*635a8641SAndroid Build Coastguard Worker };
640*635a8641SAndroid Build Coastguard Worker 
641*635a8641SAndroid Build Coastguard Worker template <typename NormalMap,
642*635a8641SAndroid Build Coastguard Worker           int kArraySize,
643*635a8641SAndroid Build Coastguard Worker           typename EqualKey,
644*635a8641SAndroid Build Coastguard Worker           typename Functor>
645*635a8641SAndroid Build Coastguard Worker inline bool small_map<NormalMap, kArraySize, EqualKey, Functor>::iterator::
646*635a8641SAndroid Build Coastguard Worker operator==(const const_iterator& other) const {
647*635a8641SAndroid Build Coastguard Worker   return other == *this;
648*635a8641SAndroid Build Coastguard Worker }
649*635a8641SAndroid Build Coastguard Worker template <typename NormalMap,
650*635a8641SAndroid Build Coastguard Worker           int kArraySize,
651*635a8641SAndroid Build Coastguard Worker           typename EqualKey,
652*635a8641SAndroid Build Coastguard Worker           typename Functor>
653*635a8641SAndroid Build Coastguard Worker inline bool small_map<NormalMap, kArraySize, EqualKey, Functor>::iterator::
654*635a8641SAndroid Build Coastguard Worker operator!=(const const_iterator& other) const {
655*635a8641SAndroid Build Coastguard Worker   return other != *this;
656*635a8641SAndroid Build Coastguard Worker }
657*635a8641SAndroid Build Coastguard Worker 
658*635a8641SAndroid Build Coastguard Worker }  // namespace base
659*635a8641SAndroid Build Coastguard Worker 
660*635a8641SAndroid Build Coastguard Worker #endif  // BASE_CONTAINERS_SMALL_MAP_H_
661