Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 namespace WTF {
     22 
     23     // This specialization is a direct copy of HashMap, with overloaded functions
     24     // to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn.
     25 
     26     // FIXME: Find a better way that doesn't require an entire copy of the HashMap template.
     27 
     28     template<typename RawKeyType, typename ValueType, typename ValueTraits, typename HashFunctions>
     29     struct RefPtrHashMapRawKeyTranslator {
     30         typedef typename ValueType::first_type KeyType;
     31         typedef typename ValueType::second_type MappedType;
     32         typedef typename ValueTraits::FirstTraits KeyTraits;
     33         typedef typename ValueTraits::SecondTraits MappedTraits;
     34 
     35         static unsigned hash(RawKeyType key) { return HashFunctions::hash(key); }
     36         static bool equal(const KeyType& a, RawKeyType b) { return HashFunctions::equal(a, b); }
     37         static void translate(ValueType& location, RawKeyType key, const MappedType& mapped)
     38         {
     39             location.first = key;
     40             location.second = mapped;
     41         }
     42     };
     43 
     44     template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
     45     class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> : public FastAllocBase {
     46     private:
     47         typedef KeyTraitsArg KeyTraits;
     48         typedef MappedTraitsArg MappedTraits;
     49         typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
     50 
     51     public:
     52         typedef typename KeyTraits::TraitType KeyType;
     53         typedef T* RawKeyType;
     54         typedef typename MappedTraits::TraitType MappedType;
     55         typedef typename ValueTraits::TraitType ValueType;
     56 
     57     private:
     58         typedef HashArg HashFunctions;
     59 
     60         typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
     61             HashFunctions, ValueTraits, KeyTraits> HashTableType;
     62 
     63         typedef RefPtrHashMapRawKeyTranslator<RawKeyType, ValueType, ValueTraits, HashFunctions>
     64             RawKeyTranslator;
     65 
     66     public:
     67         typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
     68         typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
     69 
     70         void swap(HashMap&);
     71 
     72         int size() const;
     73         int capacity() const;
     74         bool isEmpty() const;
     75 
     76         // iterators iterate over pairs of keys and values
     77         iterator begin();
     78         iterator end();
     79         const_iterator begin() const;
     80         const_iterator end() const;
     81 
     82         iterator find(const KeyType&);
     83         iterator find(RawKeyType);
     84         const_iterator find(const KeyType&) const;
     85         const_iterator find(RawKeyType) const;
     86         bool contains(const KeyType&) const;
     87         bool contains(RawKeyType) const;
     88         MappedType get(const KeyType&) const;
     89         MappedType get(RawKeyType) const;
     90         MappedType inlineGet(RawKeyType) const;
     91 
     92         // replaces value but not key if key is already present
     93         // return value is a pair of the iterator to the key location,
     94         // and a boolean that's true if a new value was actually added
     95         pair<iterator, bool> set(const KeyType&, const MappedType&);
     96         pair<iterator, bool> set(RawKeyType, const MappedType&);
     97 
     98         // does nothing if key is already present
     99         // return value is a pair of the iterator to the key location,
    100         // and a boolean that's true if a new value was actually added
    101         pair<iterator, bool> add(const KeyType&, const MappedType&);
    102         pair<iterator, bool> add(RawKeyType, const MappedType&);
    103 
    104         void remove(const KeyType&);
    105         void remove(RawKeyType);
    106         void remove(iterator);
    107         void clear();
    108 
    109         MappedType take(const KeyType&); // efficient combination of get with remove
    110         MappedType take(RawKeyType); // efficient combination of get with remove
    111 
    112     private:
    113         pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
    114         pair<iterator, bool> inlineAdd(RawKeyType, const MappedType&);
    115 
    116         HashTableType m_impl;
    117     };
    118 
    119     template<typename T, typename U, typename V, typename W, typename X>
    120     inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other)
    121     {
    122         m_impl.swap(other.m_impl);
    123     }
    124 
    125     template<typename T, typename U, typename V, typename W, typename X>
    126     inline int HashMap<RefPtr<T>, U, V, W, X>::size() const
    127     {
    128         return m_impl.size();
    129     }
    130 
    131     template<typename T, typename U, typename V, typename W, typename X>
    132     inline int HashMap<RefPtr<T>, U, V, W, X>::capacity() const
    133     {
    134         return m_impl.capacity();
    135     }
    136 
    137     template<typename T, typename U, typename V, typename W, typename X>
    138     inline bool HashMap<RefPtr<T>, U, V, W, X>::isEmpty() const
    139     {
    140         return m_impl.isEmpty();
    141     }
    142 
    143     template<typename T, typename U, typename V, typename W, typename X>
    144     inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::begin()
    145     {
    146         return m_impl.begin();
    147     }
    148 
    149     template<typename T, typename U, typename V, typename W, typename X>
    150     inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::end()
    151     {
    152         return m_impl.end();
    153     }
    154 
    155     template<typename T, typename U, typename V, typename W, typename X>
    156     inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::begin() const
    157     {
    158         return m_impl.begin();
    159     }
    160 
    161     template<typename T, typename U, typename V, typename W, typename X>
    162     inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::end() const
    163     {
    164         return m_impl.end();
    165     }
    166 
    167     template<typename T, typename U, typename V, typename W, typename X>
    168     inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key)
    169     {
    170         return m_impl.find(key);
    171     }
    172 
    173     template<typename T, typename U, typename V, typename W, typename X>
    174     inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key)
    175     {
    176         return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
    177     }
    178 
    179     template<typename T, typename U, typename V, typename W, typename X>
    180     inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const
    181     {
    182         return m_impl.find(key);
    183     }
    184 
    185     template<typename T, typename U, typename V, typename W, typename X>
    186     inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const
    187     {
    188         return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
    189     }
    190 
    191     template<typename T, typename U, typename V, typename W, typename X>
    192     inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const
    193     {
    194         return m_impl.contains(key);
    195     }
    196 
    197     template<typename T, typename U, typename V, typename W, typename X>
    198     inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const
    199     {
    200         return m_impl.template contains<RawKeyType, RawKeyTranslator>(key);
    201     }
    202 
    203     template<typename T, typename U, typename V, typename W, typename X>
    204     inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    205     HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
    206     {
    207         typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
    208         return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
    209     }
    210 
    211     template<typename T, typename U, typename V, typename W, typename X>
    212     inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    213     HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, const MappedType& mapped)
    214     {
    215         return m_impl.template add<RawKeyType, MappedType, RawKeyTranslator>(key, mapped);
    216     }
    217 
    218     template<typename T, typename U, typename V, typename W, typename X>
    219     pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    220     HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
    221     {
    222         pair<iterator, bool> result = inlineAdd(key, mapped);
    223         if (!result.second) {
    224             // add call above didn't change anything, so set the mapped value
    225             result.first->second = mapped;
    226         }
    227         return result;
    228     }
    229 
    230     template<typename T, typename U, typename V, typename W, typename X>
    231     pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    232     HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, const MappedType& mapped)
    233     {
    234         pair<iterator, bool> result = inlineAdd(key, mapped);
    235         if (!result.second) {
    236             // add call above didn't change anything, so set the mapped value
    237             result.first->second = mapped;
    238         }
    239         return result;
    240     }
    241 
    242     template<typename T, typename U, typename V, typename W, typename X>
    243     pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    244     HashMap<RefPtr<T>, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
    245     {
    246         return inlineAdd(key, mapped);
    247     }
    248 
    249     template<typename T, typename U, typename V, typename W, typename X>
    250     pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
    251     HashMap<RefPtr<T>, U, V, W, X>::add(RawKeyType key, const MappedType& mapped)
    252     {
    253         return inlineAdd(key, mapped);
    254     }
    255 
    256     template<typename T, typename U, typename V, typename W, typename MappedTraits>
    257     typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
    258     HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const
    259     {
    260         ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
    261         if (!entry)
    262             return MappedTraits::emptyValue();
    263         return entry->second;
    264     }
    265 
    266     template<typename T, typename U, typename V, typename W, typename MappedTraits>
    267     typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
    268     inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const
    269     {
    270         ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<RawKeyType, RawKeyTranslator>(key);
    271         if (!entry)
    272             return MappedTraits::emptyValue();
    273         return entry->second;
    274     }
    275 
    276     template<typename T, typename U, typename V, typename W, typename MappedTraits>
    277     typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
    278     HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
    279     {
    280         return inlineGet(key);
    281     }
    282 
    283     template<typename T, typename U, typename V, typename W, typename X>
    284     inline void HashMap<RefPtr<T>, U, V, W, X>::remove(iterator it)
    285     {
    286         if (it.m_impl == m_impl.end())
    287             return;
    288         m_impl.internalCheckTableConsistency();
    289         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
    290     }
    291 
    292     template<typename T, typename U, typename V, typename W, typename X>
    293     inline void HashMap<RefPtr<T>, U, V, W, X>::remove(const KeyType& key)
    294     {
    295         remove(find(key));
    296     }
    297 
    298     template<typename T, typename U, typename V, typename W, typename X>
    299     inline void HashMap<RefPtr<T>, U, V, W, X>::remove(RawKeyType key)
    300     {
    301         remove(find(key));
    302     }
    303 
    304     template<typename T, typename U, typename V, typename W, typename X>
    305     inline void HashMap<RefPtr<T>, U, V, W, X>::clear()
    306     {
    307         m_impl.clear();
    308     }
    309 
    310     template<typename T, typename U, typename V, typename W, typename MappedTraits>
    311     typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
    312     HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(const KeyType& key)
    313     {
    314         // This can probably be made more efficient to avoid ref/deref churn.
    315         iterator it = find(key);
    316         if (it == end())
    317             return MappedTraits::emptyValue();
    318         typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
    319         remove(it);
    320         return result;
    321     }
    322 
    323     template<typename T, typename U, typename V, typename W, typename MappedTraits>
    324     typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
    325     HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(RawKeyType key)
    326     {
    327         // This can probably be made more efficient to avoid ref/deref churn.
    328         iterator it = find(key);
    329         if (it == end())
    330             return MappedTraits::emptyValue();
    331         typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
    332         remove(it);
    333         return result;
    334     }
    335 
    336 } // namespace WTF
    337