• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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