// 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 <memory> #include <utility> #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/macros.h" #include "base/stl_util.h" namespace base { // Deprecated. Use std::unordered_map instead. https://crbug.com/579229 // // This type acts like a hash_map<K, std::unique_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_