/* * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef WTF_HashCountedSet_h #define WTF_HashCountedSet_h #include "wtf/Assertions.h" #include "wtf/HashMap.h" #include "wtf/Vector.h" namespace WTF { // An unordered hash set that keeps track of how many times you added an item to // the set. The iterators have fields ->key and ->value that return the set // members and their counts, respectively. template < typename Value, typename HashFunctions = typename DefaultHash::Hash, typename Traits = HashTraits, typename Allocator = PartitionAllocator> class HashCountedSet { WTF_USE_ALLOCATOR(HashCountedSet, Allocator); WTF_MAKE_NONCOPYABLE(HashCountedSet); private: typedef HashMap, Allocator> ImplType; public: typedef Value ValueType; typedef typename ImplType::iterator iterator; typedef typename ImplType::const_iterator const_iterator; typedef typename ImplType::AddResult AddResult; HashCountedSet() {} void swap(HashCountedSet& other) { m_impl.swap(other.m_impl); } unsigned size() const { return m_impl.size(); } unsigned capacity() const { return m_impl.capacity(); } bool isEmpty() const { return m_impl.isEmpty(); } // Iterators iterate over pairs of values (called key) and counts (called // value). iterator begin() { return m_impl.begin(); } iterator end() { return m_impl.end(); } const_iterator begin() const { return m_impl.begin(); } const_iterator end() const { return m_impl.end(); } iterator find(const ValueType& value) { return m_impl.find(value); } const_iterator find(const ValueType& value) const { return m_impl.find(value); } bool contains(const ValueType& value ) const { return m_impl.contains(value); } unsigned count(const ValueType& value ) const { return m_impl.get(value); } // Increases the count if an equal value is already present the return value // is a pair of an iterator to the new value's location, and a bool that is // true if an new entry was added. AddResult add(const ValueType&); // Reduces the count of the value, and removes it if count goes down to // zero, returns true if the value is removed. bool remove(const ValueType& value) { return remove(find(value)); } bool remove(iterator); // Removes the value, regardless of its count. void removeAll(const ValueType& value) { removeAll(find(value)); } void removeAll(iterator); // Clears the whole set. void clear() { m_impl.clear(); } template void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); } private: ImplType m_impl; }; template inline typename HashCountedSet::AddResult HashCountedSet::add(const ValueType& value) { AddResult result = m_impl.add(value, 0); ++result.storedValue->value; return result; } template inline bool HashCountedSet::remove(iterator it) { if (it == end()) return false; unsigned oldVal = it->value; ASSERT(oldVal); unsigned newVal = oldVal - 1; if (newVal) { it->value = newVal; return false; } m_impl.remove(it); return true; } template inline void HashCountedSet::removeAll(iterator it) { if (it == end()) return; m_impl.remove(it); } template inline void copyToVector(const HashCountedSet& collection, VectorType& vector) { typedef typename HashCountedSet::const_iterator iterator; { // Disallow GC across resize allocation, see crbug.com/568173 typename VectorType::GCForbiddenScope scope; vector.resize(collection.size()); } iterator it = collection.begin(); iterator end = collection.end(); for (unsigned i = 0; it != end; ++it, ++i) vector[i] = *it; } template inline void copyToVector(const HashCountedSet& collection, Vector& vector) { typedef typename HashCountedSet::const_iterator iterator; { // Disallow GC across resize allocation, see crbug.com/568173 typename Vector::GCForbiddenScope scope; vector.resize(collection.size()); } iterator it = collection.begin(); iterator end = collection.end(); for (unsigned i = 0; it != end; ++it, ++i) vector[i] = (*it).key; } #if !ENABLE(OILPAN) template struct NeedsTracing> { static const bool value = false; }; #endif } // namespace WTF using WTF::HashCountedSet; #endif // WTF_HashCountedSet_h