This source file includes following definitions.
- Clear
 
- GetEntry
 
- Put
 
- Get
 
- HasValue
 
- Erase
 
- AllocateBuckets
 
- AdjustBuckets
 
- Clear
 
- GetEntries
 
- GetEntry
 
- AddEntry
 
- Put
 
- Get
 
- HasValue
 
- Erase
 
#ifndef _NPT_MAP_H_
#define _NPT_MAP_H_
#include "NptTypes.h"
#include "NptResults.h"
#include "NptList.h"
#include "NptHash.h"
template <typename K, typename V> 
class NPT_Map 
{
public:
    
    class Entry {
    public:
        
        Entry(const K& key, const V& value) : m_Key(key), m_Value(value) {}
        Entry(const K& key) : m_Key(key) {}
        
        
        const K& GetKey()   const { return m_Key;   }
        const V& GetValue() const { return m_Value; }
        
        bool operator==(const Entry& other) const {
            return m_Key == other.m_Key && m_Value == other.m_Value;
        }
    protected:
        
        void SetValue(const V& value) { m_Value = value; }
        
        K m_Key;
        V m_Value;
        
        friend class NPT_Map<K,V>;
    };
    
    NPT_Map<K,V>() {}
    NPT_Map<K,V>(const NPT_Map<K,V>& copy);
    
    ~NPT_Map<K,V>();
    
    NPT_Result   Put(const K& key, const V& value);
    NPT_Result   Get(const K& key, V*& value) const; 
    bool         HasKey(const K& key) const { return GetEntry(key) != NULL; }
    bool         HasValue(const V& value) const;
    NPT_Result   Erase(const K& key);
    NPT_Cardinal GetEntryCount() const         { return m_Entries.GetItemCount(); }
    const NPT_List<Entry*>& GetEntries() const { return m_Entries; }
    NPT_Result   Clear();
    
    V&                  operator[](const K& key);
    const NPT_Map<K,V>& operator=(const NPT_Map<K,V>& copy);
    bool                operator==(const NPT_Map<K,V>& other) const;
    bool                operator!=(const NPT_Map<K,V>& other) const;
private:
    
    typedef typename NPT_List<Entry*>::Iterator ListIterator;
    
    Entry* GetEntry(const K& key) const;
    
    NPT_List<Entry*> m_Entries;
};
template <typename K, typename V>
NPT_Map<K,V>::NPT_Map(const NPT_Map<K,V>& copy)
{
    *this = copy;
}
template <typename K, typename V>
NPT_Map<K,V>::~NPT_Map()
{
    
    Clear();
}
template <typename K, typename V>
NPT_Result
NPT_Map<K,V>::Clear()
{
    m_Entries.Apply(NPT_ObjectDeleter<Entry>());
    m_Entries.Clear();
    return NPT_SUCCESS;
}
template <typename K, typename V>
typename NPT_Map<K,V>::Entry*
NPT_Map<K,V>::GetEntry(const K& key) const
{
    typename NPT_List<Entry*>::Iterator entry = m_Entries.GetFirstItem();
    while (entry) {
        if ((*entry)->GetKey() == key) {
            return *entry;
        }
        ++entry;
    }
    return NULL;
}
template <typename K, typename V>
NPT_Result
NPT_Map<K,V>::Put(const K& key, const V& value)
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        m_Entries.Add(new Entry(key, value));
    } else {
        
        entry->SetValue(value);
    }
    return NPT_SUCCESS;
}
template <typename K, typename V>
NPT_Result
NPT_Map<K,V>::Get(const K& key, V*& value) const
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        value = NULL;
        return NPT_ERROR_NO_SUCH_ITEM;
    } else {
        
        value = &entry->m_Value;
        return NPT_SUCCESS;
    }
}
template <typename K, typename V>
bool
NPT_Map<K,V>::HasValue(const V& value) const
{
    ListIterator entry = m_Entries.GetFirstItem();
    while (entry) {
        if (value == (*entry)->m_Value) {
            return true;
        }
        ++entry;
    }
    return false;
}
template <typename K, typename V>
const NPT_Map<K,V>&
NPT_Map<K,V>::operator=(const NPT_Map<K,V>& copy)
{
    
    if (this == ©) return copy;
    
    Clear();
    
    ListIterator entry = copy.m_Entries.GetFirstItem();
    while (entry) {
        m_Entries.Add(new Entry((*entry)->GetKey(), (*entry)->GetValue()));
        ++entry;
    }
    return *this;
}
template <typename K, typename V>
NPT_Result
NPT_Map<K,V>::Erase(const K& key)
{
    ListIterator entry = m_Entries.GetFirstItem();
    while (entry) {
        if ((*entry)->GetKey() == key) {
            delete *entry; 
                           
                           
            m_Entries.Erase(entry);
            return NPT_SUCCESS;
        }
        ++entry;
    }
    return NPT_ERROR_NO_SUCH_ITEM;
}
template <typename K, typename V>
bool
NPT_Map<K,V>::operator==(const NPT_Map<K,V>& other) const
{
    
    if (m_Entries.GetItemCount() != other.m_Entries.GetItemCount()) return false;
    
    ListIterator entry = m_Entries.GetFirstItem();
    while (entry) {
        V* value;
        if (NPT_SUCCEEDED(other.Get((*entry)->m_Key, value))) {
            
            if (!(*value == (*entry)->m_Value)) return false;
        } else {
            
            return false;
        }
        ++entry;
    }
    return true;
}
template <typename K, typename V>
bool
NPT_Map<K,V>::operator!=(const NPT_Map<K,V>& other) const
{
    return !(*this == other);
}
template <typename K, typename V>
V&
NPT_Map<K,V>::operator[](const K& key)
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        entry = new Entry(key);
        m_Entries.Add(entry);
    }
     
    return entry->m_Value;
}
template <typename K, typename V, typename HF = NPT_Hash<K> > 
class NPT_HashMap 
{
public:
    
    class Entry {
    public:
        
        Entry(NPT_UInt32 hash_value, const K& key, const V& value) : m_HashValue(hash_value), m_Key(key), m_Value(value) {}
        Entry(NPT_UInt32 hash_value, const K& key)                 : m_HashValue(hash_value), m_Key(key) {}
        
        
        const K&   GetKey()       const { return m_Key;   }
        const V&   GetValue()     const { return m_Value; }
        NPT_UInt32 GetHashValue() const { return m_HashValue; }
        
        
        bool operator==(const Entry& other) const {
            return m_HashValue == other.m_HashValue && m_Key == other.m_Key && m_Value == other.m_Value;
        }
    protected:
        
        void SetValue(const V& value) { m_Value = value; }
        
        NPT_UInt32 m_HashValue;
        K          m_Key;
        V          m_Value;
        
        friend class NPT_HashMap<K,V,HF>;
    };
    class Iterator {
    public:
        Iterator() : m_Entry(NULL), m_Map(NULL) {}
        Iterator(Entry** entry, const NPT_HashMap<K,V,HF>* map) : m_Entry(entry), m_Map(map) {}
        Iterator(const Iterator& copy) : m_Entry(copy.m_Entry), m_Map(copy.m_Map) {}
        const Entry&  operator*()  const { return **m_Entry; }
        Iterator& operator++()  { 
            if (m_Map && m_Entry) {
                do {
                    ++m_Entry;
                    if (m_Entry >= &m_Map->m_Buckets[1<<m_Map->m_BucketCountLog]) {
                        m_Entry = NULL;
                    } else {
                        if (*m_Entry) break;
                    }
                } while (m_Entry);
            }
            return (*this); 
        }
        Iterator operator++(int) { 
            Iterator saved_this = *this;
            ++(*this);
            return saved_this;
        }
        operator bool() const {
            return m_Entry != NULL;
        }
        bool operator==(const Iterator& other) const {
            return m_Map == other.m_Map && m_Entry == other.m_Entry;
        }
        bool operator!=(const Iterator& other) const {
            return !(*this == other);
        }
        void operator=(const Iterator& other) {
            m_Entry = other.m_Entry;
            m_Map   = other.m_Map;
        }
    private:
        
        friend class NPT_HashMap<K,V,HF>;
        
        Entry**                    m_Entry;
        const NPT_HashMap<K,V,HF>* m_Map;
    };
    
    NPT_HashMap<K,V,HF>();
    NPT_HashMap<K,V,HF>(const HF& hasher);
    NPT_HashMap<K,V,HF>(const NPT_HashMap<K,V,HF>& copy);
    
    ~NPT_HashMap<K,V,HF>();
    
    NPT_Result   Put(const K& key, const V& value);
    NPT_Result   Get(const K& key, V*& value) const; 
    bool         HasKey(const K& key) const { return GetEntry(key) != NULL; }
    bool         HasValue(const V& value) const;
    NPT_Result   Erase(const K& key);
    NPT_Cardinal GetEntryCount() const { return m_EntryCount; }
    Iterator     GetEntries() const;
    NPT_Result   Clear();
    
    
    
    
    template <typename X> 
    NPT_Result Apply(const X& function) const
    {                          
        for (int i=0; i<(1<<m_BucketCountLog); i++) {
            if (m_Buckets[i]) {
                function(m_Buckets[i]);
            }
        }
        return NPT_SUCCESS;
    }
    
    V&                         operator[](const K& key);
    const NPT_HashMap<K,V,HF>& operator=(const NPT_HashMap<K,V,HF>& copy);
    bool                       operator==(const NPT_HashMap<K,V,HF>& other) const;
    bool                       operator!=(const NPT_HashMap<K,V,HF>& other) const;
private:
    
    Entry*     GetEntry(const K& key, NPT_UInt32* position=NULL) const;
    NPT_Result AddEntry(Entry* entry);
    void       AllocateBuckets(unsigned int count_log);
    void       AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink=false);
    
    
    HF           m_Hasher;
    Entry**      m_Buckets;
    NPT_Cardinal m_BucketCountLog;
    NPT_Cardinal m_EntryCount;
};
template <typename K, typename V, typename HF>
NPT_HashMap<K,V,HF>::NPT_HashMap() :
    m_Buckets(NULL),
    m_EntryCount(0)
{
    AllocateBuckets(4);
}
template <typename K, typename V, typename HF>
NPT_HashMap<K,V,HF>::NPT_HashMap(const HF& hasher) :
    m_Hasher(hasher),
    m_Buckets(NULL),
    m_EntryCount(0)
{
    AllocateBuckets(4);
}
template <typename K, typename V, typename HF>
NPT_HashMap<K,V,HF>::NPT_HashMap(const NPT_HashMap<K,V,HF>& copy) :
    m_Buckets(NULL),
    m_BucketCountLog(0),
    m_EntryCount(0)
{
    *this = copy;
}
template <typename K, typename V, typename HF>
NPT_HashMap<K,V,HF>::~NPT_HashMap()
{
    for (int i=0; i<(1<<m_BucketCountLog); i++) {
        delete m_Buckets[i];
    }
    delete[] m_Buckets;
}
template <typename K, typename V, typename HF>
void
NPT_HashMap<K,V,HF>::AllocateBuckets(unsigned int count_log)
{
    m_Buckets = new Entry*[1<<count_log];
    m_BucketCountLog = count_log;
    for (int i=0; i<(1<<count_log); i++) {
        m_Buckets[i] = NULL;
    }
}
template <typename K, typename V, typename HF>
void
NPT_HashMap<K,V,HF>::AdjustBuckets(NPT_Cardinal entry_count, bool allow_shrink)
{
    Entry** buckets = NULL;
    unsigned int bucket_count = 1<<m_BucketCountLog;
    if (2*entry_count >= bucket_count) {
        
        buckets = m_Buckets;
        AllocateBuckets(m_BucketCountLog+1);
    } else if (allow_shrink && (5*entry_count < bucket_count) && m_BucketCountLog > 4) {
        
        buckets = m_Buckets;
        AllocateBuckets(m_BucketCountLog-1);
    }
    if (buckets) {
        m_EntryCount = 0;
        for (unsigned int i=0; i<bucket_count; i++) {
            if (buckets[i]) AddEntry(buckets[i]);
        }
        delete[] buckets;
    }
}
template <typename K, typename V, typename HF>
NPT_Result
NPT_HashMap<K,V,HF>::Clear()
{
    if (m_Buckets) {
        for (int i=0; i<(1<<m_BucketCountLog); i++) {
            delete m_Buckets[i];
        }
        delete[] m_Buckets;
    }
    m_EntryCount = 0;
    AllocateBuckets(4);
    
    return NPT_SUCCESS;
}
template <typename K, typename V, typename HF>
typename NPT_HashMap<K,V,HF>::Iterator
NPT_HashMap<K,V,HF>::GetEntries() const
{
    for (int i=0; i<(1<<m_BucketCountLog); i++) {
        if (m_Buckets[i]) {
            return Iterator(&m_Buckets[i], this);
        }
    }
    return Iterator(NULL, this);
}
template <typename K, typename V, typename HF>
typename NPT_HashMap<K,V,HF>::Entry*
NPT_HashMap<K,V,HF>::GetEntry(const K& key, NPT_UInt32* position) const
{
    NPT_UInt32 hash_value = m_Hasher(key);
    NPT_UInt32 mask       = (1<<m_BucketCountLog)-1;
    NPT_UInt32 cursor     = hash_value & mask;
    while (m_Buckets[cursor]) {
        Entry* entry = m_Buckets[cursor];
        if (entry->m_HashValue == hash_value &&
            entry->m_Key       == key) {
            if (position) *position = cursor;
            return entry;
        }
        cursor = (cursor + 1) & mask;
    }
    
    return NULL;
}
template <typename K, typename V, typename HF>
NPT_Result
NPT_HashMap<K,V,HF>::AddEntry(Entry* entry)
{
    AdjustBuckets(m_EntryCount+1);
    NPT_UInt32 hash_value = entry->m_HashValue;
    NPT_UInt32 mask       = (1<<m_BucketCountLog)-1;
    NPT_UInt32 cursor     = hash_value & mask;
    while (m_Buckets[cursor]) {
        cursor = (cursor + 1) & mask;
    }
    m_Buckets[cursor] = entry;
    ++m_EntryCount;
    
    return NPT_SUCCESS;
}
template <typename K, typename V, typename HF>
NPT_Result
NPT_HashMap<K,V,HF>::Put(const K& key, const V& value)
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        return AddEntry(new Entry(m_Hasher(key), key, value));
    } else {
        
        entry->SetValue(value);
    }
    return NPT_SUCCESS;
}
template <typename K, typename V, typename HF>
NPT_Result
NPT_HashMap<K,V,HF>::Get(const K& key, V*& value) const
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        value = NULL;
        return NPT_ERROR_NO_SUCH_ITEM;
    } else {
        
        value = &entry->m_Value;
        return NPT_SUCCESS;
    }
}
template <typename K, typename V, typename HF>
bool
NPT_HashMap<K,V,HF>::HasValue(const V& value) const
{
    for (int i=0; i<(1<<m_BucketCountLog); i++) {
        if (m_Buckets[i] && m_Buckets[i]->m_Value == value) {
            return true;
        }
    }
    return false;
}
template <typename K, typename V, typename HF>
NPT_Result
NPT_HashMap<K,V,HF>::Erase(const K& key)
{
    NPT_UInt32 position;
    Entry* entry = GetEntry(key, &position);
    if (entry == NULL) {
        return NPT_ERROR_NO_SUCH_ITEM;
    }
    
    
    m_Buckets[position] = NULL;
    
    
    
    
    NPT_UInt32 mask = (1<<m_BucketCountLog)-1;
    for (NPT_UInt32 cursor = (position+1) & mask; m_Buckets[cursor]; cursor = (cursor + 1) & mask) {
        NPT_UInt32 target = m_Buckets[cursor]->m_HashValue & mask;
        
        
        
        if ( (position <= cursor) ?
             ((position < target) && (target <= cursor)) :
             ((position < target) || (target <= cursor)) ) {
             continue;
        }
        
        
        m_Buckets[position] = m_Buckets[cursor];
        m_Buckets[cursor] = NULL;
        position = cursor;
    }
        
    
    delete entry;
    --m_EntryCount;
    AdjustBuckets(m_EntryCount, true);
    return NPT_SUCCESS;
}
template <typename K, typename V, typename HF>
const NPT_HashMap<K,V,HF>&
NPT_HashMap<K,V,HF>::operator=(const NPT_HashMap<K,V,HF>& copy)
{
    
    if (this == ©) return copy;
    
    Clear();
    
    AdjustBuckets(copy.m_EntryCount);
    
    
    for (int i=0; i<1<<copy.m_BucketCountLog; i++) {
        if (copy.m_Buckets[i]) {
            AddEntry(new Entry(m_Hasher(copy.m_Buckets[i]->GetKey()),
                               copy.m_Buckets[i]->GetKey(), 
                               copy.m_Buckets[i]->GetValue()));
        }
    }
    
    return *this;
}
template <typename K, typename V, typename HF>
bool
NPT_HashMap<K,V,HF>::operator==(const NPT_HashMap<K,V,HF>& other) const
{
    
    if (m_EntryCount != other.m_EntryCount) return false;
    
    
    for (int i=0; i<(1<<m_BucketCountLog); i++) {
        Entry* entry = m_Buckets[i];
        if (entry == NULL) continue;
        Entry* other_entry = other.GetEntry(entry->m_Key);
        if (other_entry == NULL || !(other_entry->m_Value == entry->m_Value)) {
            return false;
        }
    }
    
    return true;
}
template <typename K, typename V, typename HF>
bool
NPT_HashMap<K,V,HF>::operator!=(const NPT_HashMap<K,V,HF>& other) const
{
    return !(*this == other);
}
template <typename K, typename V, typename HF>
V&
NPT_HashMap<K,V,HF>::operator[](const K& key)
{
    Entry* entry = GetEntry(key);
    if (entry == NULL) {
        
        entry = new Entry(m_Hasher(key), key);
        AddEntry(entry);
    }
     
    return entry->m_Value;
}
template <class T>
class NPT_MapEntryValueDeleter {
public:
    void operator()(T* entry) const {
        delete entry->GetValue();
    }
};
#endif