#pragma once #include #include "Array.h" namespace Framework { template 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 friend class HashMap; }; template class MapIterator { private: int bucketIndex; Iterator< MapEntry > iterator; Array< MapEntry >** buckets; int bucketCount; public: MapIterator( Array< MapEntry >** buckets, int bucketCount, int bucketIndex, Iterator< MapEntry > iterator ) { while( bucketIndex < bucketCount && (!buckets[ bucketIndex ] || buckets[ bucketIndex ]->getEintragAnzahl() == 0) ) { bucketIndex++; iterator = Iterator< MapEntry >( 0 ); } if( bucketIndex < bucketCount ) { if( iterator ) this->iterator = iterator; else this->iterator = buckets[ bucketIndex ]->begin(); } else { this->iterator = Iterator< MapEntry >( 0 ); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; } this->buckets = buckets; this->bucketCount = bucketCount; this->bucketIndex = bucketIndex; } MapIterator( const MapIterator< K, V >& it ) { iterator = it.iterator; buckets = it.buckets; bucketCount = it.bucketCount; bucketIndex = it.bucketIndex; } MapIterator< K, V >& operator=( MapIterator< K, V > r ) { iterator = r.iterator; buckets = r.buckets; bucketCount = r.bucketCount; bucketIndex = r.bucketIndex; return *this; } bool hasNext() { if( iterator && iterator.hasNext() ) return 1; int ind = bucketIndex + 1; while( ind < bucketCount && (!buckets[ ind ] || buckets[ ind ]->getEintragAnzahl() == 0) ) ind++; return ind < bucketCount; } MapEntry operator*() { return iterator; } MapIterator< K, V > next() { if( bucketIndex >= bucketCount ) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range( (char*)err ); } if( iterator.hasNext() ) return MapIterator( buckets, bucketCount, bucketIndex, iterator.next() ); else return MapIterator( buckets, bucketCount, bucketIndex + 1, Iterator< MapEntry >( 0 ) ); } operator bool() { return bucketIndex < bucketCount; } operator MapEntry() { if( bucketIndex >= bucketCount ) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range( (char*)err ); } return iterator.val(); } MapIterator< K, V >& operator++() //! prefix { ++iterator; if( !iterator ) { while( bucketIndex < bucketCount && (!buckets[ bucketIndex ] || buckets[ bucketIndex ]->getEintragAnzahl() == 0) ) bucketIndex++; if( bucketIndex < bucketCount ) this->iterator = buckets[ bucketIndex ]->begin(); else { this->iterator = Iterator< MapEntry >( 0 ); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; } } return *this; } MapIterator< K, V > operator++( int ) //! postfix { Iterator< TYP > temp( *this ); ++(*this); return temp; } MapIterator< K, V > operator->() { if( bucketIndex >= bucketCount ) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range( (char*)err ); } return iterator.val(); } void set( MapEntry val ) { if( bucketIndex < bucketCount ) iterator.set( val ); else { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range( (char*)err ); } } bool operator!=( MapIterator< K, V >& r ) { return buckets != r.buckets || iterator != r.iterator; } }; template class HashMap : public virtual ReferenceCounter { private: Array< MapEntry >** buckets; int bucketCount; std::function hash; int size; public: HashMap( int bucketCount, std::function hash ) : ReferenceCounter(), buckets( new Array< MapEntry >* [ bucketCount ] ), bucketCount( bucketCount ), hash( hash ), size( 0 ) { memset( buckets, 0, sizeof( Array< MapEntry > * ) * 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 = abs( hash( key ) ) % bucketCount; if( !buckets[ index ] ) buckets[ index ] = new Array< MapEntry>(); for( auto iterator = buckets[ index ]->begin(); iterator; iterator++ ) { if( iterator._.getKey() == key ) { iterator.set( MapEntry( key, value ) ); return; } } buckets[ index ]->add( MapEntry( key, value ) ); size++; } void remove( K key ) { int index = abs( hash( key ) ) % bucketCount; if( !buckets[ index ] ) return; int listIndex = 0; for( auto bucket : *buckets[ index ] ) { if( bucket.getKey() == key ) { bucket.remove( listIndex ); size--; return; } listIndex++; } } V get( K key ) const { int index = abs( hash( key ) ) % bucketCount; if( !buckets[ index ] ) throw "element not found"; for( auto iterator : *buckets[ index ] ) { if( iterator.getKey() == key ) return iterator.getValue(); } throw "element not found"; } V safeGet( K key, V fallback ) const { int index = abs( hash( key ) ) % bucketCount; if( !buckets[ index ] ) return fallback; for( auto bucket : *buckets[ index ] ) { if( bucket.getKey() == key ) return bucket.getValue(); } return fallback; } bool has( K key ) const { int index = abs( hash( key ) ) % bucketCount; if( !buckets[ index ] ) return 0; for( auto bucket : buckets[ index ] ) { if( bucket.getKey() == key ) return 1; } return 0; } int getSize() const { return size; } MapIterator begin() { return MapIterator( buckets, bucketCount, 0, Iterator< MapEntry >( 0 ) ); } MapIterator end() { return MapIterator( 0, 0, 0, Iterator< MapEntry >( 0 ) ); } }; }