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