+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// ==++==
-//
-
-//
-
-//
-// ==--==
-
-/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XX XX
-XX hashtable<K,V,H,P,A,KO> XX
-XX XX
-XX Implemented using a vector of list iterators begin and end whose range XX
-XX is a single bucket. A chain of buckets is maintained in a linked list XX
-XX (doubly) for holding the key-value pairs. XX
-XX XX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-*/
-
-#pragma once
-
-#include "hash.h"
-#include "functional.h"
-#include "allocator.h"
-#include "vector.h"
-#include "list.h"
-#include "pair.h"
-
-namespace jitstd
-{
-
-static const float kflDefaultLoadFactor = 3.0f;
-
-template <typename Key,
- typename Value = Key,
- typename Hash = jitstd::hash<Key>,
- typename Pred = jitstd::equal_to<Key>,
- typename Alloc = jitstd::allocator<Value>,
- typename KeyOf = jitstd::identity<Value>>
-class hashtable
-{
-public:
- typedef Key key_type;
- typedef Value value_type;
- typedef Hash hasher;
- typedef Pred key_equal;
- typedef Alloc allocator_type;
- typedef typename allocator_type::pointer pointer;
- typedef typename allocator_type::const_pointer const_pointer;
- typedef typename allocator_type::reference reference;
- typedef typename allocator_type::const_reference const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef typename list<Value, Alloc>::iterator iterator;
- typedef typename list<Value, Alloc>::reverse_iterator reverse_iterator;
- typedef typename list<Value, Alloc>::const_iterator const_iterator;
- typedef typename list<Value, Alloc>::iterator local_iterator;
-
-protected:
- hashtable();
-
- typedef pair<iterator, iterator> BucketEntry;
- typedef vector<BucketEntry, typename Alloc::template rebind<BucketEntry>::allocator> Buckets;
- typedef list<Value, typename Alloc::template rebind<Value>::allocator> Elements;
-
-protected:
- explicit hashtable(size_type,
- const allocator_type& a,
- const KeyOf& keyOf = KeyOf());
-
- hashtable(size_type n,
- const hasher& hf,
- const key_equal& eq,
- const allocator_type& a,
- const KeyOf& keyOf = KeyOf());
-
- template<typename InputIterator>
- hashtable(
- InputIterator f, InputIterator l,
- size_type n,
- const hasher& hf,
- const key_equal& eq,
- const allocator_type& a,
- const KeyOf& keyOf = KeyOf());
-
- explicit hashtable(const allocator_type& a, const KeyOf& keyOf = KeyOf());
-
- hashtable(const hashtable& other);
-
- ~hashtable();
-
-public:
- hashtable& operator=(const hashtable& other);
-
- allocator_type get_allocator() const;
-
- bool empty() const;
-
- size_type size() const;
- size_type max_size() const;
-
- iterator begin();
- iterator end();
-
- // Even though we have an unordered set and there is no concept of forward and
- // reverse, rbegin will just return the first element inserted. This is not in STL.
- reverse_iterator rbegin();
- reverse_iterator rend();
-
- const_iterator begin() const;
- const_iterator end() const;
- const_iterator cbegin() const;
- const_iterator cend() const;
- local_iterator begin(size_type size);
- local_iterator end(size_type size);
-
- pair<iterator, bool> insert(const value_type& value);
- iterator insert(const_iterator, const value_type& value);
- template<typename InputIterator>
- void insert(InputIterator first, InputIterator last);
-
- iterator erase(iterator position);
- size_type erase(const key_type& key);
- iterator erase(iterator first, iterator last);
-
- void clear();
- void swap(hashtable& table);
-
- hasher hash_function() const;
- key_equal key_eq() const;
-
- const_iterator find(const key_type& key) const;
- iterator find(const key_type& key);
-
- size_type count(const key_type& key) const;
-
- size_type bucket_count() const;
- size_type max_bucket_count() const;
-
- size_type bucket_size(size_type size) const;
- size_type bucket(const key_type& key) const;
-
- float load_factor() const;
- float max_load_factor() const;
- void max_load_factor(float);
-
- void rehash(size_type);
-
-protected:
- template <typename Compare>
- iterator find(const key_type&, const Compare& comp);
-
- // helpers
- bool check_load();
- void copy_helper(const hashtable& other);
- size_type hash_helper(const key_type& value, size_type buckets) const;
- pair<iterator, bool> insert_helper(const value_type& value, Buckets& buckets, Elements& elements, bool fRehashing);
- iterator erase_helper(const_iterator position);
- void debug_check();
-
-private:
-
- // member objects
- Hash m_hasher;
- Alloc m_allocator;
- Pred m_pred;
-
- Buckets m_buckets;
- Elements m_elements;
- size_type m_nSize;
- KeyOf m_keyOf;
-
- // metadata
- float m_flMaxLoadFactor;
-};
-
-} // end of namespace jitstd
-
-
-namespace jitstd
-{
-
-// We can't leave this permanently enabled -- it makes algorithms cubic, and causes tests to time out.
-// Enable when/if you have reason to believe there's a problem in hashtable.
-#define JITSTD_DO_HASHTABLE_DEBUGCHECK 0
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::debug_check()
-{
-#if JITSTD_DO_HASHTABLE_DEBUGCHECK
- for (iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
- {
- size_type nHash = hash_helper(m_keyOf(*iter), m_buckets.size());
- BucketEntry& entry = m_buckets[nHash];
- iterator iter2 = entry.first;
- bool present = false;
- while (iter2 != entry.second)
- {
- if (iter2 == iter)
- {
- present = true;
- }
- iter2++;
- }
- if (!present)
- {
- present = false;
- }
- assert(present);
- }
-#endif
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-template <typename Compare>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::find(const key_type& key, const Compare& comp)
-{
- if (empty())
- {
- return end();
- }
- size_type nHash = hash_helper(key, m_buckets.size());
- BucketEntry& entry = m_buckets[nHash];
- for (iterator i = entry.first; i != entry.second; ++i)
- {
- if (comp(m_keyOf(*i), key))
- {
- return i;
- }
- }
- return end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-bool hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::check_load()
-{
- float flLoadFactor = load_factor();
- if (flLoadFactor > m_flMaxLoadFactor)
- {
- rehash(m_buckets.size());
- return true;
- }
- return false;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::erase_helper(const_iterator position)
-{
- const Key& key = m_keyOf(*position);
- size_type nHash = hash_helper(key, m_buckets.size());
- BucketEntry& entry = m_buckets[nHash];
- iterator eraseNext = end();
- for (iterator first = entry.first; first != entry.second; ++first)
- {
- if (m_pred(m_keyOf(*first), key))
- {
- if (first == entry.first)
- {
- if (first != m_elements.begin())
- {
- iterator update = first;
- update--;
- size_type nUpdateHash = hash_helper(m_keyOf(*update), m_buckets.size());
- if (nUpdateHash != nHash)
- {
- BucketEntry& updateEntry = m_buckets[nUpdateHash];
- if (updateEntry.second == first)
- {
- updateEntry.second = first;
- updateEntry.second++;
- }
- if (updateEntry.first == first)
- {
- updateEntry.first = first;
- updateEntry.first++;
- }
- }
- }
- entry.first = m_elements.erase(first);
- eraseNext = entry.first;
- }
- else
- {
- eraseNext = m_elements.erase(first);
- }
-
- --m_nSize;
-#ifdef DEBUG
- debug_check();
-#endif
- return eraseNext;
- }
- }
- return end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-pair<typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator, bool>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::insert_helper(
- const Value& value, Buckets& buckets, Elements& elements, bool fRehashing)
-{
- const Key& key = m_keyOf(value);
- size_t nHash = hash_helper(key, buckets.size());
- BucketEntry& entry = buckets[nHash];
-
- iterator ret;
- if (entry.first == entry.second)
- {
- entry.first = elements.insert(elements.begin(), value);
- entry.second = entry.first;
- entry.second++; // end iterator is one past always.
- ret = entry.first;
- }
- else
- {
- for (iterator first = entry.first; first != entry.second; ++first)
- {
- if (m_pred(m_keyOf(*first), key))
- {
- return pair<iterator, bool>(first, false);
- }
- }
- iterator firstNext = entry.first;
- firstNext++;
- ret = elements.insert(firstNext, value);
- if (entry.second == entry.first)
- {
- entry.second = firstNext;
- }
- }
- bool fRehashed = false;
- if (!fRehashing)
- {
- m_nSize += 1;
- fRehashed = check_load();
- }
-
-#ifdef DEBUG
- debug_check();
-#endif
-
- return pair<iterator, bool>(fRehashed ? find(key, m_pred) : ret, true);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hash_helper(
- const key_type& key, size_type buckets) const
-{
- return m_hasher(key) % buckets;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::rehash(size_type n)
-{
- size_type nCurBuckets = m_buckets.size();
- float flLoadFactor = load_factor();
- if (nCurBuckets >= n && flLoadFactor <= m_flMaxLoadFactor)
- {
- return;
- }
-
- size_type nBuckets = max(nCurBuckets, 1);
- if (flLoadFactor > m_flMaxLoadFactor)
- {
- nBuckets *= 2;
- }
-
- if (nBuckets < n)
- {
- nBuckets = n;
- }
-
- Buckets buckets(m_allocator);
- Elements elements(m_allocator);
-
- buckets.resize(nBuckets, BucketEntry(m_elements.end(), m_elements.end())); // both equal means empty.
- for (typename Elements::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
- {
- (void) insert_helper(*iter, buckets, elements, true);
- }
- m_buckets.swap(buckets);
- m_elements.swap(elements);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hashtable(
- size_type n,
- allocator_type const& allocator,
- const KeyOf& keyOf)
- : m_allocator(allocator)
- , m_buckets(Alloc::template rebind<hashtable::BucketEntry>::allocator(allocator))
- , m_elements(allocator)
- , m_flMaxLoadFactor(kflDefaultLoadFactor)
- , m_nSize(0)
- , m_keyOf(keyOf)
-{
- rehash(n);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hashtable(
- size_type n,
- hasher const& hf,
- key_equal const& eq,
- allocator_type const& allocator,
- const KeyOf& keyOf)
- : m_hasher(hf)
- , m_pred(eq)
- , m_allocator(allocator)
- , m_buckets(Alloc::template rebind<BucketEntry>::allocator(allocator))
- , m_elements(allocator)
- , m_flMaxLoadFactor(kflDefaultLoadFactor)
- , m_nSize(0)
- , m_keyOf(keyOf)
-{
- rehash(n);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-template<typename InputIterator>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hashtable(
- InputIterator f, InputIterator l,
- size_type n,
- const hasher& hf,
- const key_equal& eq,
- const allocator_type& allocator,
- const KeyOf& keyOf)
- : m_hasher(hf)
- , m_pred(eq)
- , m_allocator(allocator)
- , m_buckets(Alloc::template rebind<BucketEntry>::allocator(allocator))
- , m_elements(allocator)
- , m_flMaxLoadFactor(kflDefaultLoadFactor)
- , m_nSize(0)
- , m_keyOf(keyOf)
-{
- rehash(n);
- insert(this->first, this->last);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hashtable(const allocator_type& allocator, const KeyOf& keyOf)
- : m_allocator(allocator)
- , m_buckets(Alloc::template rebind<BucketEntry>::allocator(allocator))
- , m_elements(allocator)
- , m_flMaxLoadFactor(kflDefaultLoadFactor)
- , m_nSize(0)
- , m_keyOf(keyOf)
-{
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::copy_helper(const hashtable& other)
-{
- m_buckets.clear();
- m_elements.clear();
- m_nSize = 0;
-
- rehash(other.m_buckets.size());
- for (const_iterator i = other.m_elements.begin(); i != other.m_elements.end(); ++i)
- {
- insert_helper(*i, m_buckets, m_elements, false);
- }
- m_nSize = other.m_nSize;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hashtable(const hashtable& other)
- : m_hasher(other.m_hasher)
- , m_pred(other.m_pred)
- , m_allocator(other.m_allocator)
- , m_flMaxLoadFactor(other.m_flMaxLoadFactor)
- , m_keyOf(other.m_keyOf)
- , m_elements(other.m_allocator)
- , m_buckets(other.m_allocator)
-{
- copy_helper(other);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::~hashtable()
-{
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>&
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::operator=(hashtable const& other)
-{
- m_hasher = other.m_hasher;
- m_pred = other.m_pred;
- m_allocator = other.m_allocator;
- m_flMaxLoadFactor = other.m_flMaxLoadFactor;
- m_keyOf = other.m_keyOf;
- copy_helper(other);
- return *this;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::allocator_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::get_allocator() const
-{
- return m_allocator;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-bool hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::empty() const
-{
- return m_nSize == 0;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size() const
-{
- return m_nSize;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::max_size() const
-{
- return ((size_type)(-1)) >> 1;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::begin()
-{
- return m_elements.begin();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::reverse_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::rbegin()
-{
- return m_elements.rbegin();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::end()
-{
- return m_elements.end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::reverse_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::rend()
-{
- return m_elements.rend();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::const_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::begin() const
-{
- return m_elements.begin();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::const_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::end() const
-{
- return m_elements.end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::const_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::cbegin() const
-{
- return m_elements.begin();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::const_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::cend() const
-{
- return m_elements.end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-jitstd::pair<typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator, bool>
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::insert(const Value& val)
-{
- // Allocate some space first.
- rehash(2);
- return insert_helper(val, m_buckets, m_elements, false);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::insert(const_iterator position, const Value& value)
-{
- // Allocate some space first.
- rehash(2);
-
- // We will not use the hint here, we can consider doing this later.
- return insert_helper(this->val, m_buckets, m_elements, false).first;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-template<typename InputIterator>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::insert(InputIterator first, InputIterator last)
-{
- // Allocate some space first.
- rehash(2);
- while (first != last)
- {
- (void) insert_helper(*first, m_buckets, m_elements, false);
- ++first;
- }
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::erase(iterator position)
-{
- return erase_helper(position);
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::erase(const key_type& key)
-{
- iterator iter = erase_helper(find(key));
- return iter == end() ? 0 : 1;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::erase(iterator first, iterator last)
-{
- iterator iter = end();
- while (first != last)
- {
- iter = erase_helper(find(m_keyOf(*first)));
- ++first;
- }
- return iter;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::clear()
-{
- m_buckets.clear();
- m_elements.clear();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::swap(hashtable& set)
-{
- std::swap(set.m_buckets, m_buckets);
- std::swap(set.m_elements, m_elements);
- std::swap(set.m_flLoadFactor, this->m_flLoadFactor);
- std::swap(set.m_flMaxLoadFactor, this->m_flMaxLoadFactor);
- std::swap(set.m_keyOf, this->m_keyOf);
-}
-
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hasher
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::hash_function() const
-{
- return m_hasher;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::key_equal
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::key_eq() const
-{
- return m_pred;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::const_iterator
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::find(const key_type& key) const
-{
- if (empty())
- {
- return end();
- }
- size_type nHash = hash_helper(key, m_buckets.size());
- BucketEntry& entry = m_buckets[nHash];
- for (iterator i = entry.first; i != entry.second; ++i)
- {
- if (m_pred(m_keyOf(*i), key))
- {
- return i;
- }
- }
- return end();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::iterator
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::find(const key_type& key)
-{
- if (empty())
- {
- return end();
- }
- size_type nHash = hash_helper(key, m_buckets.size());
- BucketEntry& entry = m_buckets[nHash];
- for (iterator i = entry.first; i != entry.second; ++i)
- {
- if (m_pred(m_keyOf(*i), key))
- {
- return i;
- }
- }
- return end();
-}
-
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
- hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::count(const key_type& key) const
-{
- size_type nCount = 0;
- size_type nHash = hash_helper(key, m_buckets.size());
- BucketEntry& bucket = m_buckets[nHash];
- for (iterator i = bucket.first; i != bucket.second; ++i)
- {
- if (m_pred(m_keyOf(*i), key))
- {
- ++nCount;
- }
- }
- return nCount;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::bucket_count() const
-{
- return m_buckets.size();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::max_bucket_count() const
-{
- return m_buckets.size();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::bucket_size(size_type size) const
-{
- rehash(size);
- return bucket_count();
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::size_type
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::bucket(const key_type& key) const
-{
- return hash_helper(key, m_buckets.size());
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::local_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::begin(size_type size)
-{
- return m_buckets[size].first;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-typename hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::local_iterator
-hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::end(size_type size)
-{
- return m_buckets[size].second;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-float hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::load_factor() const
-{
- return m_nSize ? (((float) m_nSize) / m_buckets.size()) : 0;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-float hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::max_load_factor() const
-{
- return m_flMaxLoadFactor;
-}
-
-template <typename Key, typename Value, typename Hash, typename Pred, typename Alloc, typename KeyOf>
-void hashtable<Key, Value, Hash, Pred, Alloc, KeyOf>::max_load_factor(float flLoadFactor)
-{
- m_flMaxLoadFactor = flLoadFactor;
- rehash(m_buckets.size());
-}
-
-} // end of namespace jitstd.
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// ==++==
-//
-
-//
-
-//
-// ==--==
-
-/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XX XX
-XX unordered_map<K,V,H,P,A> XX
-XX Derives from hashtable for most implementation. Inserted elements are XX
-XX value pairs and the hash key is provided by the helper method that XX
-XX extracts the key from the key value pair XX
-XX XX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-*/
-
-#pragma once
-
-#include "hashtable.h"
-
-namespace jitstd
-{
-
-template <typename Key, typename Value>
-struct pair_key
-{
- Key& operator()(const jitstd::pair<Key, Value>& pair) const
- {
- return pair.first;
- }
-};
-
-template<typename Key,
- typename Value,
- typename Hash = jitstd::hash<Key>,
- typename Pred = jitstd::equal_to<Key>,
- typename Alloc = jitstd::allocator<jitstd::pair<const Key, Value> > >
-class unordered_map
- : public hashtable<Key, pair<const Key, Value>, Hash, Pred, Alloc, pair_key<const Key, Value>>
-{
-public:
-
- typedef Key key_type;
- typedef Value mapped_type;
- typedef jitstd::pair<const Key, Value> value_type;
- typedef Hash hasher;
- typedef Pred key_equal;
- typedef Alloc allocator_type;
- typedef typename allocator_type::pointer pointer;
- typedef typename allocator_type::const_pointer const_pointer;
- typedef typename allocator_type::reference reference;
- typedef typename allocator_type::const_reference const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
-
- explicit unordered_map(size_type size, const hasher& hasher, const key_equal& pred, const allocator_type& allocator);
- explicit unordered_map(size_type size, const allocator_type& allocator);
- template<typename InputIterator>
- unordered_map(InputIterator, InputIterator,
- size_type size,
- const hasher& hasher,
- const key_equal& pred,
- const allocator_type& allocator);
-
- unordered_map(const unordered_map& map);
- explicit unordered_map(const allocator_type& allocator);
- unordered_map(const unordered_map& map, const allocator_type& allocator);
- ~unordered_map();
-
- unordered_map& operator=(unordered_map const&);
- mapped_type& operator[](const Key& key);
- mapped_type& operator[](key_type&& key);
-
- typename unordered_map<Key, Value, Hash, Pred, Alloc>::iterator insert(const key_type& key, const mapped_type& value);
-
-private:
- typedef hashtable<Key, pair<const Key, Value>, Hash, Pred, Alloc, pair_key<const Key, Value>> base_type;
-};
-
-}
-
-
-namespace jitstd
-{
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(size_type size, const hasher& hasher, const key_equal& pred, const allocator_type& allocator)
- : base_type(size, hasher, pred, allocator)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(size_type size, const allocator_type& allocator)
- : base_type(size, allocator)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-template<typename InputIterator>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(InputIterator first, InputIterator last,
- size_type size,
- const hasher& hasher,
- const key_equal& pred,
- const allocator_type& allocator)
- : base_type(first, last, size, hasher, pred, allocator)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(const unordered_map& map)
- : base_type(map)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(const allocator_type& allocator)
- : base_type(allocator)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::unordered_map(const unordered_map& map, const allocator_type& allocator)
- : base_type(map, allocator)
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>::~unordered_map()
-{
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-unordered_map<Key, Value, Hash, Pred, Alloc>& unordered_map<Key, Value, Hash, Pred, Alloc>::operator=(const unordered_map& map)
-{
- base_type::operator=(map);
- return *this;
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-Value& unordered_map<Key, Value, Hash, Pred, Alloc>::operator[](const Key& key)
-{
- typename unordered_map<Key, Value, Hash, Pred, Alloc>::iterator iter = base_type::find(key, this->key_eq());
- if (iter == this->end())
- {
- iter = base_type::insert(jitstd::pair<const Key, mapped_type>(key, mapped_type())).first;
- }
- return (*iter).second;
-}
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-Value& unordered_map<Key, Value, Hash, Pred, Alloc>::operator[](key_type&& key)
-{
- typename unordered_map<Key, Value, Hash, Pred, Alloc>::iterator iter = base_type::find(key, this->key_eq());
- if (iter == this->end())
- {
- iter = base_type::insert(jitstd::pair<const Key, mapped_type>(key, mapped_type())).first;
- }
- return (*iter).second;
-}
-
-
-template<typename Key, typename Value, typename Hash, typename Pred, typename Alloc>
-typename unordered_map<Key, Value, Hash, Pred, Alloc>::iterator
-unordered_map<Key, Value, Hash, Pred, Alloc>::insert(const key_type& key, const mapped_type& value)
-{
- typename unordered_map<Key, Value, Hash, Pred, Alloc>::iterator iter = base_type::find(key, this->key_eq());
- iter = base_type::insert(jitstd::pair<const Key, mapped_type>(key, value)).first;
- return iter;
-}
-
-}