|
@@ -0,0 +1,138 @@
|
|
|
+#pragma once
|
|
|
+
|
|
|
+#include <functional>
|
|
|
+
|
|
|
+#include "Array.h"
|
|
|
+
|
|
|
+namespace Framework
|
|
|
+{
|
|
|
+ template<typename K, typename V>
|
|
|
+ class MapEntry
|
|
|
+ {
|
|
|
+ private:
|
|
|
+ K key;
|
|
|
+ V value;
|
|
|
+
|
|
|
+ public:
|
|
|
+ MapEntry()
|
|
|
+ {}
|
|
|
+
|
|
|
+ MapEntry( K key, V value )
|
|
|
+ : key( key ),
|
|
|
+ value( value )
|
|
|
+ {}
|
|
|
+
|
|
|
+ K getKey()
|
|
|
+ {
|
|
|
+ return key;
|
|
|
+ }
|
|
|
+
|
|
|
+ V getValue()
|
|
|
+ {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ template<typename K2, typename V2>
|
|
|
+ friend class HashMap;
|
|
|
+ };
|
|
|
+
|
|
|
+ template<typename K, typename V>
|
|
|
+ class HashMap : public virtual ReferenceCounter
|
|
|
+ {
|
|
|
+ private:
|
|
|
+ Array< MapEntry<K, V> > **buckets;
|
|
|
+ int bucketCount;
|
|
|
+ std::function<int( K )> hash;
|
|
|
+
|
|
|
+ public:
|
|
|
+ HashMap( int bucketCount, std::function<int( K )> hash )
|
|
|
+ : ReferenceCounter(),
|
|
|
+ buckets( new Array< MapEntry<K, V> > *[ bucketCount ] ),
|
|
|
+ bucketCount( bucketCount ),
|
|
|
+ hash( hash )
|
|
|
+ {
|
|
|
+ memset( buckets, 0, sizeof( Array< MapEntry<K, V> > * ) * bucketCount );
|
|
|
+ }
|
|
|
+
|
|
|
+ ~HashMap()
|
|
|
+ {
|
|
|
+ for( int i = 0; i < bucketCount; i++ )
|
|
|
+ {
|
|
|
+ if( buckets[ i ] )
|
|
|
+ buckets[ i ]->release();
|
|
|
+ }
|
|
|
+ delete[] buckets;
|
|
|
+ }
|
|
|
+
|
|
|
+ void put( K key, V value )
|
|
|
+ {
|
|
|
+ int index = hash( key ) % bucketCount;
|
|
|
+ if( !buckets[ index ] )
|
|
|
+ buckets[ index ] = new Array< MapEntry<K, V>>();
|
|
|
+ for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ )
|
|
|
+ {
|
|
|
+ if( iterator._.getKey() == key )
|
|
|
+ {
|
|
|
+ iterator.set( MapEntry<K, V>( key, value ) );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ buckets[ index ]->add( MapEntry<K, V>( key, value ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ void remove( K key )
|
|
|
+ {
|
|
|
+ int index = hash( key ) % bucketCount;
|
|
|
+ if( !buckets[ index ] )
|
|
|
+ return;
|
|
|
+ int listIndex = 0;
|
|
|
+ for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++, listIndex++ )
|
|
|
+ {
|
|
|
+ if( iterator._.getKey() == key )
|
|
|
+ {
|
|
|
+ buckets[ index ]->remove( listIndex );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ V get( K key ) const
|
|
|
+ {
|
|
|
+ int index = hash( key ) % bucketCount;
|
|
|
+ if( !buckets[ index ] )
|
|
|
+ throw "element not found";
|
|
|
+ for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ )
|
|
|
+ {
|
|
|
+ if( iterator._.getKey() == key )
|
|
|
+ return iterator._.getValue();
|
|
|
+ }
|
|
|
+ throw "element not found";
|
|
|
+ }
|
|
|
+
|
|
|
+ V safeGet( K key, V fallback ) const
|
|
|
+ {
|
|
|
+ int index = hash( key ) % bucketCount;
|
|
|
+ if( !buckets[ index ] )
|
|
|
+ return fallback;
|
|
|
+ for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ )
|
|
|
+ {
|
|
|
+ if( iterator._.getKey() == key )
|
|
|
+ return iterator._.getValue();
|
|
|
+ }
|
|
|
+ return fallback;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool has( K key ) const
|
|
|
+ {
|
|
|
+ int index = hash( key ) % bucketCount;
|
|
|
+ if( !buckets[ index ] )
|
|
|
+ return 0;
|
|
|
+ for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ )
|
|
|
+ {
|
|
|
+ if( iterator._.getKey() == key )
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|