1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_ 6 #define BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_ 7 8 #include <stddef.h> 9 10 #include <algorithm> 11 #include <memory> 12 #include <utility> 13 14 #include "base/containers/hash_tables.h" 15 #include "base/logging.h" 16 #include "base/macros.h" 17 #include "base/stl_util.h" 18 19 namespace base { 20 21 // Deprecated. Use std::unordered_map instead. https://crbug.com/579229 22 // 23 // This type acts like a hash_map<K, std::unique_ptr<V, D> >, based on top of 24 // base::hash_map. The ScopedPtrHashMap has ownership of all values in the data 25 // structure. 26 template <typename Key, typename ScopedPtr> 27 class ScopedPtrHashMap { 28 typedef base::hash_map<Key, typename ScopedPtr::element_type*> Container; 29 30 public: 31 typedef typename Container::key_type key_type; 32 typedef typename Container::mapped_type mapped_type; 33 typedef typename Container::value_type value_type; 34 typedef typename Container::iterator iterator; 35 typedef typename Container::const_iterator const_iterator; 36 ScopedPtrHashMap()37 ScopedPtrHashMap() {} 38 ~ScopedPtrHashMap()39 ~ScopedPtrHashMap() { clear(); } 40 swap(ScopedPtrHashMap<Key,ScopedPtr> & other)41 void swap(ScopedPtrHashMap<Key, ScopedPtr>& other) { 42 data_.swap(other.data_); 43 } 44 45 // Replaces value but not key if key is already present. set(const Key & key,ScopedPtr data)46 iterator set(const Key& key, ScopedPtr data) { 47 iterator it = find(key); 48 if (it != end()) { 49 // Let ScopedPtr decide how to delete. For example, it may use custom 50 // deleter. 51 ScopedPtr(it->second).reset(); 52 it->second = data.release(); 53 return it; 54 } 55 56 return data_.insert(std::make_pair(key, data.release())).first; 57 } 58 59 // Does nothing if key is already present add(const Key & key,ScopedPtr data)60 std::pair<iterator, bool> add(const Key& key, ScopedPtr data) { 61 std::pair<iterator, bool> result = 62 data_.insert(std::make_pair(key, data.get())); 63 if (result.second) 64 ::ignore_result(data.release()); 65 return result; 66 } 67 erase(iterator it)68 void erase(iterator it) { 69 // Let ScopedPtr decide how to delete. 70 ScopedPtr(it->second).reset(); 71 data_.erase(it); 72 } 73 erase(const Key & k)74 size_t erase(const Key& k) { 75 iterator it = data_.find(k); 76 if (it == data_.end()) 77 return 0; 78 erase(it); 79 return 1; 80 } 81 take(iterator it)82 ScopedPtr take(iterator it) { 83 DCHECK(it != data_.end()); 84 if (it == data_.end()) 85 return ScopedPtr(); 86 87 ScopedPtr ret(it->second); 88 it->second = NULL; 89 return ret; 90 } 91 take(const Key & k)92 ScopedPtr take(const Key& k) { 93 iterator it = find(k); 94 if (it == data_.end()) 95 return ScopedPtr(); 96 97 return take(it); 98 } 99 take_and_erase(iterator it)100 ScopedPtr take_and_erase(iterator it) { 101 DCHECK(it != data_.end()); 102 if (it == data_.end()) 103 return ScopedPtr(); 104 105 ScopedPtr ret(it->second); 106 data_.erase(it); 107 return ret; 108 } 109 take_and_erase(const Key & k)110 ScopedPtr take_and_erase(const Key& k) { 111 iterator it = find(k); 112 if (it == data_.end()) 113 return ScopedPtr(); 114 115 return take_and_erase(it); 116 } 117 118 // Returns the element in the hash_map that matches the given key. 119 // If no such element exists it returns NULL. get(const Key & k)120 typename ScopedPtr::element_type* get(const Key& k) const { 121 const_iterator it = find(k); 122 if (it == end()) 123 return NULL; 124 return it->second; 125 } 126 contains(const Key & k)127 inline bool contains(const Key& k) const { return data_.count(k) > 0; } 128 clear()129 inline void clear() { 130 auto it = data_.begin(); 131 while (it != data_.end()) { 132 // NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. 133 // Deleting the value does not always invalidate the iterator, but it may 134 // do so if the key is a pointer into the value object. 135 auto temp = it; 136 ++it; 137 // Let ScopedPtr decide how to delete. 138 ScopedPtr(temp->second).reset(); 139 } 140 data_.clear(); 141 } 142 find(const Key & k)143 inline const_iterator find(const Key& k) const { return data_.find(k); } find(const Key & k)144 inline iterator find(const Key& k) { return data_.find(k); } 145 count(const Key & k)146 inline size_t count(const Key& k) const { return data_.count(k); } equal_range(const Key & k)147 inline std::pair<const_iterator, const_iterator> equal_range( 148 const Key& k) const { 149 return data_.equal_range(k); 150 } equal_range(const Key & k)151 inline std::pair<iterator, iterator> equal_range(const Key& k) { 152 return data_.equal_range(k); 153 } 154 size()155 inline size_t size() const { return data_.size(); } max_size()156 inline size_t max_size() const { return data_.max_size(); } 157 empty()158 inline bool empty() const { return data_.empty(); } 159 bucket_count()160 inline size_t bucket_count() const { return data_.bucket_count(); } resize(size_t size)161 inline void resize(size_t size) { return data_.resize(size); } 162 begin()163 inline iterator begin() { return data_.begin(); } begin()164 inline const_iterator begin() const { return data_.begin(); } end()165 inline iterator end() { return data_.end(); } end()166 inline const_iterator end() const { return data_.end(); } 167 168 private: 169 Container data_; 170 171 DISALLOW_COPY_AND_ASSIGN(ScopedPtrHashMap); 172 }; 173 174 } // namespace base 175 176 #endif // BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_ 177