• 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 <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 
ScopedPtrHashMap()35   ScopedPtrHashMap() {}
36 
~ScopedPtrHashMap()37   ~ScopedPtrHashMap() { clear(); }
38 
swap(ScopedPtrHashMap<Key,ScopedPtr> & other)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.
set(const Key & key,ScopedPtr data)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
add(const Key & key,ScopedPtr data)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 
erase(iterator it)66   void erase(iterator it) {
67     // Let ScopedPtr decide how to delete.
68     ScopedPtr(it->second).reset();
69     data_.erase(it);
70   }
71 
erase(const Key & k)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 
take(iterator it)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 
take(const Key & k)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 
take_and_erase(iterator it)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 
take_and_erase(const Key & k)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.
get(const Key & k)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 
contains(const Key & k)125   inline bool contains(const Key& k) const { return data_.count(k) > 0; }
126 
clear()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 
find(const Key & k)141   inline const_iterator find(const Key& k) const { return data_.find(k); }
find(const Key & k)142   inline iterator find(const Key& k) { return data_.find(k); }
143 
count(const Key & k)144   inline size_t count(const Key& k) const { return data_.count(k); }
equal_range(const Key & k)145   inline std::pair<const_iterator, const_iterator> equal_range(
146       const Key& k) const {
147     return data_.equal_range(k);
148   }
equal_range(const Key & k)149   inline std::pair<iterator, iterator> equal_range(const Key& k) {
150     return data_.equal_range(k);
151   }
152 
size()153   inline size_t size() const { return data_.size(); }
max_size()154   inline size_t max_size() const { return data_.max_size(); }
155 
empty()156   inline bool empty() const { return data_.empty(); }
157 
bucket_count()158   inline size_t bucket_count() const { return data_.bucket_count(); }
resize(size_t size)159   inline void resize(size_t size) { return data_.resize(size); }
160 
begin()161   inline iterator begin() { return data_.begin(); }
begin()162   inline const_iterator begin() const { return data_.begin(); }
end()163   inline iterator end() { return data_.end(); }
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