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