| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 // | 4 // | 
| 5 // This is a simplistic insertion-ordered map.  It behaves similarly to an STL | 5 // This is a simplistic insertion-ordered map.  It behaves similarly to an STL | 
| 6 // map, but only implements a small subset of the map's methods.  Internally, we | 6 // map, but only implements a small subset of the map's methods.  Internally, we | 
| 7 // just keep a map and a list going in parallel. | 7 // just keep a map and a list going in parallel. | 
| 8 // | 8 // | 
| 9 // This class provides no thread safety guarantees, beyond what you would | 9 // This class provides no thread safety guarantees, beyond what you would | 
| 10 // normally see with std::list. | 10 // normally see with std::list. | 
| 11 // | 11 // | 
| 12 // Iterators should be stable in the face of mutations, except for an | 12 // Iterators should be stable in the face of mutations, except for an | 
| 13 // iterator pointing to an element that was just deleted. | 13 // iterator pointing to an element that was just deleted. | 
| 14 | 14 | 
| 15 #ifndef UTIL_GTL_LINKED_HASH_MAP_H_ | 15 #ifndef UTIL_GTL_LINKED_HASH_MAP_H_ | 
| 16 #define UTIL_GTL_LINKED_HASH_MAP_H_ | 16 #define UTIL_GTL_LINKED_HASH_MAP_H_ | 
| 17 | 17 | 
| 18 #include <list> | 18 #include <list> | 
| 19 #include <utility> | 19 #include <utility> | 
| 20 | 20 | 
| 21 #include "base/containers/hash_tables.h" | 21 #include "base/containers/hash_tables.h" | 
| 22 #include "base/logging.h" | 22 #include "base/logging.h" | 
| 23 | 23 | 
| 24 // This holds a list of pair<Key, Value> items.  This list is what gets | 24 // This holds a list of pair<Key, Value> items.  This list is what gets | 
| 25 // traversed, and it's iterators from this list that we return from | 25 // traversed, and it's iterators from this list that we return from | 
| 26 // begin/end/find. | 26 // begin/end/find. | 
| 27 // | 27 // | 
| 28 // We also keep a map<Key, list::iterator> for find.  Since std::list is a | 28 // We also keep a map<Key, list::iterator> for find.  Since std::list is a | 
| 29 // doubly-linked list, the iterators should remain stable. | 29 // doubly-linked list, the iterators should remain stable. | 
| 30 template<class Key, class Value> | 30 template <class Key, class Value> | 
| 31 class linked_hash_map { | 31 class linked_hash_map { | 
| 32  private: | 32  private: | 
| 33   typedef std::list<std::pair<Key, Value> > ListType; | 33   typedef std::list<std::pair<Key, Value> > ListType; | 
| 34   typedef base::hash_map<Key, typename ListType::iterator> MapType; | 34   typedef base::hash_map<Key, typename ListType::iterator> MapType; | 
| 35 | 35 | 
| 36  public: | 36  public: | 
| 37   typedef typename ListType::iterator iterator; | 37   typedef typename ListType::iterator iterator; | 
| 38   typedef typename ListType::reverse_iterator reverse_iterator; | 38   typedef typename ListType::reverse_iterator reverse_iterator; | 
| 39   typedef typename ListType::const_iterator const_iterator; | 39   typedef typename ListType::const_iterator const_iterator; | 
| 40   typedef typename ListType::const_reverse_iterator const_reverse_iterator; | 40   typedef typename ListType::const_reverse_iterator const_reverse_iterator; | 
| 41   typedef typename MapType::key_type key_type; | 41   typedef typename MapType::key_type key_type; | 
| 42   typedef typename ListType::value_type value_type; | 42   typedef typename ListType::value_type value_type; | 
| 43   typedef typename ListType::size_type size_type; | 43   typedef typename ListType::size_type size_type; | 
| 44 | 44 | 
| 45   linked_hash_map() : map_(), list_() { | 45   linked_hash_map() : map_(), list_() {} | 
| 46   } |  | 
| 47 | 46 | 
| 48   // Returns an iterator to the first (insertion-ordered) element.  Like a map, | 47   // Returns an iterator to the first (insertion-ordered) element.  Like a map, | 
| 49   // this can be dereferenced to a pair<Key, Value>. | 48   // this can be dereferenced to a pair<Key, Value>. | 
| 50   iterator begin() { | 49   iterator begin() { return list_.begin(); } | 
| 51     return list_.begin(); | 50   const_iterator begin() const { return list_.begin(); } | 
| 52   } |  | 
| 53   const_iterator begin() const { |  | 
| 54     return list_.begin(); |  | 
| 55   } |  | 
| 56 | 51 | 
| 57   // Returns an iterator beyond the last element. | 52   // Returns an iterator beyond the last element. | 
| 58   iterator end() { | 53   iterator end() { return list_.end(); } | 
| 59     return list_.end(); | 54   const_iterator end() const { return list_.end(); } | 
| 60   } |  | 
| 61   const_iterator end() const { |  | 
| 62     return list_.end(); |  | 
| 63   } |  | 
| 64 | 55 | 
| 65   // Returns an iterator to the last (insertion-ordered) element.  Like a map, | 56   // Returns an iterator to the last (insertion-ordered) element.  Like a map, | 
| 66   // this can be dereferenced to a pair<Key, Value>. | 57   // this can be dereferenced to a pair<Key, Value>. | 
| 67   reverse_iterator rbegin() { | 58   reverse_iterator rbegin() { return list_.rbegin(); } | 
| 68     return list_.rbegin(); | 59   const_reverse_iterator rbegin() const { return list_.rbegin(); } | 
| 69   } |  | 
| 70   const_reverse_iterator rbegin() const { |  | 
| 71     return list_.rbegin(); |  | 
| 72   } |  | 
| 73 | 60 | 
| 74   // Returns an iterator beyond the first element. | 61   // Returns an iterator beyond the first element. | 
| 75   reverse_iterator rend() { | 62   reverse_iterator rend() { return list_.rend(); } | 
| 76     return list_.rend(); | 63   const_reverse_iterator rend() const { return list_.rend(); } | 
| 77   } |  | 
| 78   const_reverse_iterator rend() const { |  | 
| 79     return list_.rend(); |  | 
| 80   } |  | 
| 81 | 64 | 
| 82   // Front and back accessors common to many stl containers. | 65   // Front and back accessors common to many stl containers. | 
| 83 | 66 | 
| 84   // Returns the earliest-inserted element | 67   // Returns the earliest-inserted element | 
| 85   const value_type& front() const { | 68   const value_type& front() const { return list_.front(); } | 
| 86     return list_.front(); |  | 
| 87   } |  | 
| 88 | 69 | 
| 89   // Returns the earliest-inserted element. | 70   // Returns the earliest-inserted element. | 
| 90   value_type& front() { | 71   value_type& front() { return list_.front(); } | 
| 91     return list_.front(); |  | 
| 92   } |  | 
| 93 | 72 | 
| 94   // Returns the most-recently-inserted element. | 73   // Returns the most-recently-inserted element. | 
| 95   const value_type& back() const { | 74   const value_type& back() const { return list_.back(); } | 
| 96     return list_.back(); |  | 
| 97   } |  | 
| 98 | 75 | 
| 99   // Returns the most-recently-inserted element. | 76   // Returns the most-recently-inserted element. | 
| 100   value_type& back() { | 77   value_type& back() { return list_.back(); } | 
| 101     return list_.back(); |  | 
| 102   } |  | 
| 103 | 78 | 
| 104   // Clears the map of all values. | 79   // Clears the map of all values. | 
| 105   void clear() { | 80   void clear() { | 
| 106     map_.clear(); | 81     map_.clear(); | 
| 107     list_.clear(); | 82     list_.clear(); | 
| 108   } | 83   } | 
| 109 | 84 | 
| 110   // Returns true iff the map is empty. | 85   // Returns true iff the map is empty. | 
| 111   bool empty() const { | 86   bool empty() const { return list_.empty(); } | 
| 112     return list_.empty(); |  | 
| 113   } |  | 
| 114 | 87 | 
| 115   // Erases values with the provided key.  Returns the number of elements | 88   // Erases values with the provided key.  Returns the number of elements | 
| 116   // erased.  In this implementation, this will be 0 or 1. | 89   // erased.  In this implementation, this will be 0 or 1. | 
| 117   size_type erase(const Key& key) { | 90   size_type erase(const Key& key) { | 
| 118     typename MapType::iterator found = map_.find(key); | 91     typename MapType::iterator found = map_.find(key); | 
| 119     if (found == map_.end()) return 0; | 92     if (found == map_.end()) | 
|  | 93       return 0; | 
| 120 | 94 | 
| 121     list_.erase(found->second); | 95     list_.erase(found->second); | 
| 122     map_.erase(found); | 96     map_.erase(found); | 
| 123 | 97 | 
| 124     return 1; | 98     return 1; | 
| 125   } | 99   } | 
| 126 | 100 | 
| 127   // Erases values with the provided iterator. If the provided iterator is | 101   // Erases values with the provided iterator. If the provided iterator is | 
| 128   // invalid or there is inconsistency between the map and list, a CHECK() error | 102   // invalid or there is inconsistency between the map and list, a CHECK() error | 
| 129   // will occur. | 103   // will occur. | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 167   std::pair<iterator, iterator> equal_range(const key_type& key) { | 141   std::pair<iterator, iterator> equal_range(const key_type& key) { | 
| 168     std::pair<typename MapType::iterator, typename MapType::iterator> eq_range = | 142     std::pair<typename MapType::iterator, typename MapType::iterator> eq_range = | 
| 169         map_.equal_range(key); | 143         map_.equal_range(key); | 
| 170 | 144 | 
| 171     return std::make_pair(eq_range.first->second, eq_range.second->second); | 145     return std::make_pair(eq_range.first->second, eq_range.second->second); | 
| 172   } | 146   } | 
| 173 | 147 | 
| 174   std::pair<const_iterator, const_iterator> equal_range( | 148   std::pair<const_iterator, const_iterator> equal_range( | 
| 175       const key_type& key) const { | 149       const key_type& key) const { | 
| 176     std::pair<typename MapType::const_iterator, | 150     std::pair<typename MapType::const_iterator, | 
| 177         typename MapType::const_iterator> eq_range = | 151               typename MapType::const_iterator> eq_range = | 
| 178         map_.equal_range(key); | 152         map_.equal_range(key); | 
| 179     const const_iterator& start_iter = eq_range.first != map_.end() ? | 153     const const_iterator& start_iter = | 
| 180         eq_range.first->second : end(); | 154         eq_range.first != map_.end() ? eq_range.first->second : end(); | 
| 181     const const_iterator& end_iter = eq_range.second != map_.end() ? | 155     const const_iterator& end_iter = | 
| 182         eq_range.second->second : end(); | 156         eq_range.second != map_.end() ? eq_range.second->second : end(); | 
| 183 | 157 | 
| 184     return std::make_pair(start_iter, end_iter); | 158     return std::make_pair(start_iter, end_iter); | 
| 185   } | 159   } | 
| 186 | 160 | 
| 187   // Returns the value mapped to key, or an inserted iterator to that position | 161   // Returns the value mapped to key, or an inserted iterator to that position | 
| 188   // in the map. | 162   // in the map. | 
| 189   Value& operator[](const key_type& key) { | 163   Value& operator[](const key_type& key) { | 
| 190     return (*((this->insert(std::make_pair(key, Value()))).first)).second; | 164     return (*((this->insert(std::make_pair(key, Value()))).first)).second; | 
| 191   } | 165   } | 
| 192 | 166 | 
| 193   // Inserts an element into the map | 167   // Inserts an element into the map | 
| 194   std::pair<iterator, bool> insert(const std::pair<Key, Value>& pair) { | 168   std::pair<iterator, bool> insert(const std::pair<Key, Value>& pair) { | 
| 195     // First make sure the map doesn't have a key with this value.  If it does, | 169     // First make sure the map doesn't have a key with this value.  If it does, | 
| 196     // return a pair with an iterator to it, and false indicating that we | 170     // return a pair with an iterator to it, and false indicating that we | 
| 197     // didn't insert anything. | 171     // didn't insert anything. | 
| 198     typename MapType::iterator found = map_.find(pair.first); | 172     typename MapType::iterator found = map_.find(pair.first); | 
| 199     if (found != map_.end()) return std::make_pair(found->second, false); | 173     if (found != map_.end()) | 
|  | 174       return std::make_pair(found->second, false); | 
| 200 | 175 | 
| 201     // Otherwise, insert into the list first. | 176     // Otherwise, insert into the list first. | 
| 202     list_.push_back(pair); | 177     list_.push_back(pair); | 
| 203 | 178 | 
| 204     // Obtain an iterator to the newly added element.  We do -- instead of - | 179     // Obtain an iterator to the newly added element.  We do -- instead of - | 
| 205     // since list::iterator doesn't implement operator-(). | 180     // since list::iterator doesn't implement operator-(). | 
| 206     typename ListType::iterator last = list_.end(); | 181     typename ListType::iterator last = list_.end(); | 
| 207     --last; | 182     --last; | 
| 208 | 183 | 
| 209     CHECK(map_.insert(std::make_pair(pair.first, last)).second) | 184     CHECK(map_.insert(std::make_pair(pair.first, last)).second) | 
| 210         << "Map and list are inconsistent"; | 185         << "Map and list are inconsistent"; | 
| 211 | 186 | 
| 212     return std::make_pair(last, true); | 187     return std::make_pair(last, true); | 
| 213   } | 188   } | 
| 214 | 189 | 
| 215   size_type size() const { | 190   size_type size() const { return list_.size(); } | 
| 216     return list_.size(); |  | 
| 217   } |  | 
| 218 | 191 | 
| 219   void swap(linked_hash_map& other) { | 192   void swap(linked_hash_map& other) { | 
| 220     map_.swap(other.map_); | 193     map_.swap(other.map_); | 
| 221     list_.swap(other.list_); | 194     list_.swap(other.list_); | 
| 222   } | 195   } | 
| 223 | 196 | 
| 224  private: | 197  private: | 
| 225   // The map component, used for speedy lookups | 198   // The map component, used for speedy lookups | 
| 226   MapType map_; | 199   MapType map_; | 
| 227 | 200 | 
| 228   // The list component, used for maintaining insertion order | 201   // The list component, used for maintaining insertion order | 
| 229   ListType list_; | 202   ListType list_; | 
| 230 }; | 203 }; | 
| 231 | 204 | 
| 232 #endif  // UTIL_GTL_LINKED_HASH_MAP_H_ | 205 #endif  // UTIL_GTL_LINKED_HASH_MAP_H_ | 
| OLD | NEW | 
|---|