summaryrefslogtreecommitdiff
path: root/base/containers/scoped_ptr_hash_map.h
blob: 189c3149f3ab0f46e42dce8076ee338e4575b04a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_
#define BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_

#include <stddef.h>

#include <algorithm>
#include <utility>

#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"

namespace base {

// This type acts like a hash_map<K, scoped_ptr<V, D> >, based on top of
// base::hash_map. The ScopedPtrHashMap has ownership of all values in the data
// structure.
template <typename Key, typename ScopedPtr>
class ScopedPtrHashMap {
  typedef base::hash_map<Key, typename ScopedPtr::element_type*> Container;

 public:
  typedef typename Container::key_type key_type;
  typedef typename Container::mapped_type mapped_type;
  typedef typename Container::value_type value_type;
  typedef typename Container::iterator iterator;
  typedef typename Container::const_iterator const_iterator;

  ScopedPtrHashMap() {}

  ~ScopedPtrHashMap() { clear(); }

  void swap(ScopedPtrHashMap<Key, ScopedPtr>& other) {
    data_.swap(other.data_);
  }

  // Replaces value but not key if key is already present.
  iterator set(const Key& key, ScopedPtr data) {
    iterator it = find(key);
    if (it != end()) {
      // Let ScopedPtr decide how to delete. For example, it may use custom
      // deleter.
      ScopedPtr(it->second).reset();
      it->second = data.release();
      return it;
    }

    return data_.insert(std::make_pair(key, data.release())).first;
  }

  // Does nothing if key is already present
  std::pair<iterator, bool> add(const Key& key, ScopedPtr data) {
    std::pair<iterator, bool> result =
        data_.insert(std::make_pair(key, data.get()));
    if (result.second)
      ::ignore_result(data.release());
    return result;
  }

  void erase(iterator it) {
    // Let ScopedPtr decide how to delete.
    ScopedPtr(it->second).reset();
    data_.erase(it);
  }

  size_t erase(const Key& k) {
    iterator it = data_.find(k);
    if (it == data_.end())
      return 0;
    erase(it);
    return 1;
  }

  ScopedPtr take(iterator it) {
    DCHECK(it != data_.end());
    if (it == data_.end())
      return ScopedPtr();

    ScopedPtr ret(it->second);
    it->second = NULL;
    return ret;
  }

  ScopedPtr take(const Key& k) {
    iterator it = find(k);
    if (it == data_.end())
      return ScopedPtr();

    return take(it);
  }

  ScopedPtr take_and_erase(iterator it) {
    DCHECK(it != data_.end());
    if (it == data_.end())
      return ScopedPtr();

    ScopedPtr ret(it->second);
    data_.erase(it);
    return ret;
  }

  ScopedPtr take_and_erase(const Key& k) {
    iterator it = find(k);
    if (it == data_.end())
      return ScopedPtr();

    return take_and_erase(it);
  }

  // Returns the element in the hash_map that matches the given key.
  // If no such element exists it returns NULL.
  typename ScopedPtr::element_type* get(const Key& k) const {
    const_iterator it = find(k);
    if (it == end())
      return NULL;
    return it->second;
  }

  inline bool contains(const Key& k) const { return data_.count(k) > 0; }

  inline void clear() {
    auto it = data_.begin();
    while (it != data_.end()) {
      // NOTE: Like STLDeleteContainerPointers, deleting behind the iterator.
      // Deleting the value does not always invalidate the iterator, but it may
      // do so if the key is a pointer into the value object.
      auto temp = it;
      ++it;
      // Let ScopedPtr decide how to delete.
      ScopedPtr(temp->second).reset();
    }
    data_.clear();
  }

  inline const_iterator find(const Key& k) const { return data_.find(k); }
  inline iterator find(const Key& k) { return data_.find(k); }

  inline size_t count(const Key& k) const { return data_.count(k); }
  inline std::pair<const_iterator, const_iterator> equal_range(
      const Key& k) const {
    return data_.equal_range(k);
  }
  inline std::pair<iterator, iterator> equal_range(const Key& k) {
    return data_.equal_range(k);
  }

  inline size_t size() const { return data_.size(); }
  inline size_t max_size() const { return data_.max_size(); }

  inline bool empty() const { return data_.empty(); }

  inline size_t bucket_count() const { return data_.bucket_count(); }
  inline void resize(size_t size) { return data_.resize(size); }

  inline iterator begin() { return data_.begin(); }
  inline const_iterator begin() const { return data_.begin(); }
  inline iterator end() { return data_.end(); }
  inline const_iterator end() const { return data_.end(); }

 private:
  Container data_;

  DISALLOW_COPY_AND_ASSIGN(ScopedPtrHashMap);
};

}  // namespace base

#endif  // BASE_CONTAINERS_SCOPED_PTR_HASH_MAP_H_