Hashtable.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 X-Way Rights BV
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00023 #ifndef _CLASS_BEE_UTIL_HASHTABLE_H
00024 #define _CLASS_BEE_UTIL_HASHTABLE_H
00025 
00026 #ifdef __cplusplus
00027 
00028 #include "beecrypt/c++/lang/Cloneable.h"
00029 using beecrypt::lang::Cloneable;
00030 #include "beecrypt/c++/lang/Integer.h"
00031 using beecrypt::lang::Integer;
00032 #include "beecrypt/c++/lang/IllegalStateException.h"
00033 using beecrypt::lang::IllegalStateException;
00034 #include "beecrypt/c++/lang/NullPointerException.h"
00035 using beecrypt::lang::NullPointerException;
00036 #include "beecrypt/c++/lang/OutOfMemoryError.h"
00037 using beecrypt::lang::OutOfMemoryError;
00038 #include "beecrypt/c++/lang/UnsupportedOperationException.h"
00039 using beecrypt::lang::UnsupportedOperationException;
00040 #include "beecrypt/c++/util/Map.h"
00041 using beecrypt::util::Map;
00042 #include "beecrypt/c++/util/AbstractSet.h"
00043 using beecrypt::util::AbstractSet;
00044 #include "beecrypt/c++/util/ConcurrentModificationException.h"
00045 using beecrypt::util::ConcurrentModificationException;
00046 
00047 namespace beecrypt {
00048     namespace util {
00051         template<class K, class V> class Hashtable : public Object, public virtual Map<K,V>, public virtual Cloneable
00052         {
00053         private:
00054             class Entry : public Object, public virtual Map<K,V>::Entry, public virtual Cloneable
00055             {
00056             public:
00057                 jint hash;
00058                 K* key;
00059                 V* value;
00060                 Entry* next;
00061 
00062                 Entry(jint hash, K* key, V* value, Entry* next = 0) : hash(hash), key(key), value(value), next(next)
00063                 {
00064                 }
00065                 Entry(const Entry& copy) : hash(copy.hash), key(copy.key), value(copy.value), next(copy.next ? new Entry(*copy.next) : 0)
00066                 {
00067                 }
00068                 virtual ~Entry() {}
00069 
00070                 virtual Entry* clone() const throw (CloneNotSupportedException)
00071                 {
00072                     return new Entry(*this);
00073                 }
00074                 virtual bool equals(const class Map<K,V>::Entry* e) const throw ()
00075                 {
00076                     if (this == e)
00077                         return true;
00078 
00079                     return (key ? key->equals(e->getKey()) : (e->getKey() == 0)) &&
00080                         (value ? value->equals(e->getValue()) : (e->getValue() == 0));
00081                 }
00082                 virtual bool equals(const Object* obj) const throw ()
00083                 {
00084                     if (this == obj)
00085                         return true;
00086 
00087                     if (obj)
00088                     {
00089                         const class Map<K,V>::Entry* e = dynamic_cast<const class Map<K,V>::Entry*>(obj);
00090                         if (e)
00091                             return (key ? key->equals(e->getKey()) : (e->getKey() == 0)) &&
00092                                 (value ? value->equals(e->getValue()) : (e->getValue() == 0));
00093                     }
00094                     return false;
00095                 }
00096                 virtual K* getKey() const
00097                 {
00098                     return key;
00099                 }
00100                 virtual V* getValue() const
00101                 {
00102                     return value;
00103                 }
00104                 virtual jint hashCode() const throw ()
00105                 {
00106                     return hash ^ (value ? value->hashCode() : 0);
00107                 }
00108                 virtual V* setValue(V* val)
00109                 {
00110                     if (val)
00111                     {
00112                         V* result = value;
00113 
00114                         value = val;
00115 
00116                         return result;
00117                     }
00118                     else
00119                         throw NullPointerException();
00120                 }
00121                 virtual String toString() const throw ()
00122                 {
00123                     StringBuilder tmp;
00124 
00125                     return tmp.append(key).append('=').append(value).toString();
00126                 }
00127             };
00128 
00129             class HashIter : public Object
00130             {
00131             private:
00132                       Hashtable* _ht;
00133                 const Hashtable* _const_ht;
00134 
00135             protected:
00136                 Entry* next;
00137                 Entry* current;
00138                 jint index;
00139                 jint expect;
00140 
00141             protected:
00142                 HashIter(Hashtable* h) : _ht(h), _const_ht(h)
00143                 {
00144                     expect = _const_ht->_modCount;
00145                     index = _const_ht->_table.size();
00146                     next = current = 0;
00147                     if (_const_ht->_count)
00148                         while ((index > 0) && ((next = _const_ht->_table[--index]) == 0));
00149                 }
00150                 HashIter(const Hashtable* h) : _ht(0), _const_ht(h)
00151                 {
00152                     expect = _const_ht->_modCount;
00153                     index = _const_ht->_table.size();
00154                     next = current = 0;
00155                     if (_const_ht->_count)
00156                         while ((index > 0) && ((next = _const_ht->_table[--index]) == 0));
00157                 }
00158 
00159             public:
00160                 virtual ~HashIter() {}
00161 
00162                 virtual bool hasNext() throw ()
00163                 {
00164                     return (next != 0);
00165                 }
00166                 Entry* nextEntry() throw (NoSuchElementException, ConcurrentModificationException)
00167                 {
00168                     if (_const_ht->_modCount != expect)
00169                         throw ConcurrentModificationException();
00170 
00171                     Entry* e = next;
00172                     if (!e)
00173                         throw NoSuchElementException();
00174 
00175                     next = e->next;
00176                     while (!next && index > 0)
00177                         next = _const_ht->_table[--index];
00178 
00179                     return current = e;
00180                 }
00181                 virtual void remove()
00182                 {
00183                     if (!_ht)
00184                         throw UnsupportedOperationException("Cannot remove items through const iterator");
00185 
00186                     if (!current)
00187                         throw IllegalStateException();
00188 
00189                     if (_ht->_modCount != expect)
00190                         throw ConcurrentModificationException();
00191 
00192                     K* key = current->key;
00193 
00194                     current = 0;
00195 
00196                     Entry* e = _ht->removeEntryForKey(key);
00197                     if (e)
00198                     {
00199                         collection_remove(e->key);
00200                         collection_remove(e->value);
00201 
00202                         delete e;
00203                     }
00204 
00205                     expect = _ht->_modCount;
00206                 }
00207             };
00208 
00209             class EntryIter : public HashIter, public virtual Iterator<class Map<K,V>::Entry>
00210             {
00211             public:
00212                 EntryIter(Hashtable* h) : HashIter(h)
00213                 {
00214                 }
00215                 EntryIter(const Hashtable* h) : HashIter(h)
00216                 {
00217                 }
00218                 virtual ~EntryIter() {}
00219 
00220                 virtual bool hasNext() throw ()
00221                 {
00222                     return HashIter::hasNext();
00223                 }
00224                 virtual class Map<K,V>::Entry* next() throw (NoSuchElementException)
00225                 {
00226                     return this->nextEntry();
00227                 }
00228                 virtual void remove()
00229                 {
00230                     HashIter::remove();
00231                 }
00232             };
00233 
00234             class KeyIter : public HashIter, public virtual Iterator<K>
00235             {
00236             public:
00237                 KeyIter(Hashtable* h) : HashIter(h)
00238                 {
00239                 }
00240                 KeyIter(const Hashtable* h) : HashIter(h)
00241                 {
00242                 }
00243                 virtual ~KeyIter() {}
00244 
00245                 virtual bool hasNext() throw ()
00246                 {
00247                     return HashIter::hasNext();
00248                 }
00249                 virtual K* next() throw (NoSuchElementException)
00250                 {
00251                     return this->nextEntry()->key;
00252                 }
00253                 virtual void remove()
00254                 {
00255                     HashIter::remove();
00256                 }
00257             };
00258 
00259             class ValueIter : public HashIter, public virtual Iterator<V>
00260             {
00261             public:
00262                 ValueIter(Hashtable* h) : HashIter(h)
00263                 {
00264                 }
00265                 ValueIter(const Hashtable* h) : HashIter(h)
00266                 {
00267                 }
00268                 virtual ~ValueIter() {}
00269 
00270                 virtual bool hasNext() throw ()
00271                 {
00272                     return HashIter::hasNext();
00273                 }
00274                 virtual V* next() throw (NoSuchElementException)
00275                 {
00276                     return this->nextEntry()->value;
00277                 }
00278                 virtual void remove()
00279                 {
00280                     HashIter::remove();
00281                 }
00282             };
00283 
00284             class EntrySet : public AbstractSet<class Map<K,V>::Entry>
00285             {
00286             private:
00287                 Hashtable*_ht;
00288 
00289             public:
00290                 EntrySet(Hashtable* h) : _ht(h)
00291                 {
00292                 }
00293                 virtual ~EntrySet() {}
00294 
00295                 virtual jint size() const throw ()
00296                 {
00297                     return _ht->size();
00298                 }
00299                 virtual Iterator<class Map<K,V>::Entry>* iterator()
00300                 {
00301                     return new EntryIter(_ht);
00302                 }
00303                 virtual Iterator<class Map<K,V>::Entry>* iterator() const
00304                 {
00305                     return new EntryIter(_ht);
00306                 }
00307             };
00308 
00309             class KeySet : public AbstractSet<K>
00310             {
00311             private:
00312                 Hashtable* _ht;
00313 
00314             public:
00315                 KeySet(Hashtable* h) : _ht(h)
00316                 {
00317                 }
00318                 virtual ~KeySet() {}
00319 
00320                 virtual jint size() const throw ()
00321                 {
00322                     return _ht->size();
00323                 }
00324                 virtual Iterator<K>* iterator()
00325                 {
00326                     return new KeyIter(_ht);
00327                 }
00328                 virtual Iterator<K>* iterator() const
00329                 {
00330                     return new KeyIter(_ht);
00331                 }
00332             };
00333 
00334             class ValueCollection : public AbstractCollection<V>
00335             {
00336             private:
00337                 Hashtable* _ht;
00338 
00339             public:
00340                 ValueCollection(Hashtable* h) : _ht(h)
00341                 {
00342                 }
00343                 virtual ~ValueCollection() {}
00344 
00345                 virtual jint size() const throw ()
00346                 {
00347                     return _ht->size();
00348                 }
00349                 virtual Iterator<V>* iterator()
00350                 {
00351                     return new ValueIter(_ht);
00352                 }
00353                 virtual Iterator<V>* iterator() const
00354                 {
00355                     return new ValueIter(_ht);
00356                 }
00357             };
00358 
00359         private:
00360             array<Entry*> _table;
00361             jint _count;
00362             jint _threshold;
00363             jfloat _loadFactor;
00364             jint _modCount;
00365 
00366             mutable bool _hashing;
00367             mutable Set<class Map<K,V>::Entry>* _entries;
00368             mutable Set<K>* _keys;
00369             mutable Collection<V>* _values;
00370 
00371         protected:
00372             Entry* removeEntryForKey(const K* key)
00373             {
00374                 jint hash = key->hashCode();
00375                 jint index = (hash & Integer::MAX_VALUE) % _table.size();
00376                 Entry* prev = 0;
00377                 for (Entry* e = _table[index]; e; prev = e, e = e->next)
00378                     if (hash == e->hash && key->equals(e->key))
00379                     {
00380                         _modCount++;
00381 
00382                         if (prev)
00383                             prev->next = e->next;
00384                         else
00385                             _table[index] = e->next;
00386 
00387                         _count--;
00388 
00389                         return e;
00390                     }
00391                 return 0;
00392             }
00393 
00394         public:
00395             Hashtable(jint initialCapacity = 15, jfloat loadFactor = 0.75)
00396             {
00397                 if (initialCapacity < 0 || loadFactor <= 0.0)
00398                     throw IllegalArgumentException();
00399 
00400                 if (initialCapacity == 0)
00401                     initialCapacity = 1;
00402 
00403                 _table.resize(initialCapacity);
00404                 _threshold = (jint)(initialCapacity * (_loadFactor = loadFactor));
00405 
00406                 _count = 0;
00407                 _modCount = 0;
00408 
00409                 _entries = 0;
00410                 _keys = 0;
00411                 _values = 0;
00412 
00413                 _hashing = false;
00414             }
00415             Hashtable(const Hashtable& copy) : _table(copy._table.size())
00416             {
00417                 _loadFactor = copy._loadFactor;
00418                 _threshold = copy._threshold;
00419 
00420                 _count = 0;
00421                 _modCount = 0;
00422 
00423                 _entries = 0;
00424                 _keys = 0;
00425                 _values = 0;
00426 
00427                 _hashing = false;
00428 
00429                 putAll(copy);
00430             }
00431             virtual ~Hashtable()
00432             {
00433                 clear();
00434 
00435                 delete _entries;
00436                 delete _keys;
00437                 delete _values;
00438             }
00439 
00440             virtual void clear()
00441             {
00442                 synchronized (this)
00443                 {
00444                     _modCount++;
00445 
00446                     for (jint index = _table.size(); index-- > 0; )
00447                     {
00448                         for (Entry* e = _table[index]; e; )
00449                         {
00450                             Entry *tmp = e->next;
00451 
00452                             collection_remove(e->key);
00453                             collection_remove(e->value);
00454 
00455                             delete e;
00456 
00457                             e = tmp;
00458                         }
00459                         _table[index] = 0;
00460                     }
00461                     _count = 0;
00462                 }
00463             }
00464             virtual Object* clone() const throw (CloneNotSupportedException)
00465             {
00466                 Object* result = 0;
00467 
00468                 synchronized (this)
00469                 {
00470                     result = new Hashtable(*this);
00471                 }
00472                 return result;
00473             }
00474             virtual bool contains(const Object* obj) const
00475             {
00476                 const V* value = dynamic_cast<const V*>(obj);
00477                 if (value)
00478                     return containsValue(value);
00479                 else
00480                     return false;
00481             }
00482             virtual bool containsKey(const K* key) const
00483             {
00484                 if (!key)
00485                     throw NullPointerException();
00486 
00487                 synchronized (this)
00488                 {
00489                     jint index = (key->hashCode() & Integer::MAX_VALUE) % _table.size();
00490                     for (Entry* e = _table[index]; e; e = e->next)
00491                         if (e->key->equals(key))
00492                             return true;
00493                 }
00494                 return false;
00495             }
00496             virtual bool containsValue(const V* value) const
00497             {
00498                 if (!value)
00499                     throw NullPointerException();
00500 
00501                 synchronized (this)
00502                 {
00503                     for (jint i = 0; i < _table.size(); i++)
00504                         for (Entry* e = _table[i]; e; e = e->next)
00505                             if (e->value->equals(value))
00506                                 return true;
00507                 }
00508                 return false;
00509             }
00510             virtual Set<class Map<K,V>::Entry>& entrySet()
00511             {
00512                 if (!_entries)
00513                 {
00514                     synchronized (this)
00515                     {
00516                         if (!_entries)
00517                             _entries = new EntrySet(this);
00518                     }
00519                 }
00520                 return *_entries;
00521             }
00522             virtual const Set<class Map<K,V>::Entry>& entrySet() const
00523             {
00524                 if (!_entries)
00525                 {
00526                     synchronized (this)
00527                     {
00528                         if (!_entries)
00529                             _entries = new EntrySet(const_cast<Hashtable*>(this));
00530                     }
00531                 }
00532                 return *_entries;
00533             }
00534             virtual bool equals(const Object* obj) const throw ()
00535             {
00536                 if (this == obj)
00537                     return true;
00538 
00539                 if (obj)
00540                 {
00541                     const Map<K,V>* map = dynamic_cast<const Map<K,V>*>(obj);
00542                     if (map)
00543                     {
00544                         synchronized (this)
00545                         {
00546                             if (_count != map->size())
00547                                 return false;
00548 
00549                             try
00550                             {
00551                                 bool result = true;
00552                                 Iterator<class Map<K,V>::Entry>* mit = map->entrySet().iterator();
00553                                 assert(mit != 0);
00554                                 while (mit->hasNext())
00555                                 {
00556                                     class Map<K,V>::Entry* me = mit->next();
00557                                     K* key = me->getKey();
00558                                     V* value = me->getValue();
00559                                     if (value)
00560                                     {
00561                                         if (!(map->get(key) == 0 && map->containsKey(key)))
00562                                         {
00563                                             result = false;
00564                                             break;
00565                                         }
00566                                     }
00567                                     else
00568                                     {
00569                                         if (!value->equals(map->get(key)))
00570                                         {
00571                                             result = false;
00572                                             break;
00573                                         }
00574                                     }
00575                                 }
00576                                 delete mit;
00577                                 return result;
00578                             }
00579                             catch (Exception&)
00580                             {
00581                             }
00582                         }
00583                     }
00584                 }
00585                 return false;
00586             }
00587             virtual V* get(const K* key) const
00588             {
00589                 if (key)
00590                 {
00591                     synchronized (this)
00592                     {
00593                         jint index = (key->hashCode() & Integer::MAX_VALUE) % _table.size();
00594                         for (Entry* e = _table[index]; e; e = e->next)
00595                             if (e->key->equals(key))
00596                                 return e->value;
00597                     }
00598                     return 0;
00599                 }
00600                 else
00601                     throw NullPointerException();
00602             }
00603             virtual jint hashCode() const throw ()
00604             {
00605                 jint result = 0;
00606 
00607                 synchronized (this)
00608                 {
00609                     if (_count == 0 || _hashing)
00610                         return 0;
00611 
00612                     _hashing = true;
00613 
00614                     for (jint i = 0; i < _table.size(); i++)
00615                         for (Entry* e = _table[i]; e; e = e->next)
00616                             result += e->key->hashCode() ^ e->value->hashCode();
00617 
00618                     _hashing = false;
00619                 }
00620 
00621                 return result;
00622             }
00623             virtual bool isEmpty() const throw ()
00624             {
00625                 bool result = true;
00626 
00627                 synchronized (this)
00628                 {
00629                     result = (_count == 0);
00630                 }
00631                 return result;
00632             }
00633             virtual Set<K>& keySet()
00634             {
00635                 if (_keys)
00636                 {
00637                     synchronized (this)
00638                     {
00639                         if (!_keys)
00640                             _keys = new KeySet(this);
00641                     }
00642                 }
00643                 return *_keys;
00644             }
00645             virtual const Set<K>& keySet() const
00646             {
00647                 if (_keys)
00648                 {
00649                     synchronized (this)
00650                     {
00651                         if (!_keys)
00652                             _keys = new KeySet(const_cast<Hashtable*>(this));
00653                     }
00654                 }
00655                 return *_keys;
00656             }
00657             virtual V* put(K* key, V* value)
00658             {
00659                 if (key && value)
00660                 {
00661                     jint hash = key->hashCode();
00662 
00663                     synchronized (this)
00664                     {
00665                         jint index = (hash & Integer::MAX_VALUE) % _table.size();
00666 
00667                         for (Entry* e = _table[index]; e != 0; e = e->next)
00668                         {
00669                             if (key->equals(e->key))
00670                             {
00671                                 // Existing key
00672                                 V* result = e->value;
00673                                 e->value = value;
00674 
00675                                 collection_attach(value);
00676                                 collection_detach(result);
00677 
00678                                 return result;
00679                             }
00680                         }
00681 
00682                         // Non-existing key
00683                         _modCount++;
00684 
00685                         if (_count >= _threshold)
00686                         {
00687                             // Re-hash
00688                             jint oldsize = _table.size();
00689 
00690                             if (oldsize == Integer::MAX_VALUE)
00691                                 throw OutOfMemoryError();
00692 
00693                             jint newsize = (_table.size() << 1) + 1;
00694 
00695                             // test if overflow occured
00696                             if (newsize < oldsize)
00697                                 newsize = Integer::MAX_VALUE;
00698 
00699                             array<Entry*> retable(newsize);
00700 
00701                             for (jint i = oldsize; i-- > 0; )
00702                             {
00703                                 for (Entry* e = _table[i]; e != 0; )
00704                                 {
00705                                     Entry* tmp = e->next;
00706 
00707                                     index = (e->hash & Integer::MAX_VALUE) % newsize;
00708                                     e->next = retable[index];
00709                                     retable[index] = e;
00710                                     e = tmp;
00711                                 }
00712                             }
00713 
00714                             // Swap retable and _table contents
00715                             _table.swap(retable);
00716 
00717                             _threshold = (jint)(newsize * _loadFactor);
00718 
00719                             index = (hash & Integer::MAX_VALUE) % _table.size();
00720                         }
00721 
00722                         Entry* tmp = _table[index];
00723                         _table[index] = new Entry(hash, key, value, tmp);
00724                         _count++;
00725                         collection_attach(key);
00726                         collection_attach(value);
00727                     }
00728                     return 0;
00729                 }
00730                 else
00731                     throw NullPointerException();
00732             }
00733             virtual void putAll(const Map<K,V>& m)
00734             {
00735                 Iterator<class Map<K,V>::Entry>* mit = m.entrySet().iterator();
00736                 assert(mit != 0);
00737                 while (mit->hasNext())
00738                 {
00739                     class Map<K,V>::Entry* e = mit->next();
00740                     V* tmp = put(e->getKey(), e->getValue());
00741                     collection_rcheck(tmp);
00742                 }
00743                 delete mit;
00744             }
00745             virtual V* remove(const K* key)
00746             {
00747                 if (key)
00748                 {
00749                     Entry* e = removeEntryForKey(key);
00750                     if (e)
00751                     {
00752                         V* result = e->value;
00753 
00754                         collection_remove(e->key);
00755                         collection_detach(result);
00756 
00757                         delete e;
00758 
00759                         return result;
00760                     }
00761                     return 0;
00762                 }
00763                 else
00764                     throw NullPointerException();
00765             }
00766             virtual jint size() const throw ()
00767             {
00768                 jint result = 0;
00769 
00770                 synchronized (this)
00771                 {
00772                     result = _count;
00773                 }
00774                 return result;
00775             }
00776             virtual Collection<V>& values()
00777             {
00778                 if (!_values)
00779                 {
00780                     synchronized (this)
00781                     {
00782                         if (!_values)
00783                             _values = new ValueCollection(this);
00784                     }
00785                 }
00786                 return *_values;
00787             }
00788             virtual const Collection<V>& values() const
00789             {
00790                 if (!_values)
00791                 {
00792                     synchronized (this)
00793                     {
00794                         if (!_values)
00795                             _values = new ValueCollection(const_cast<Hashtable*>(this));
00796                     }
00797                 }
00798                 return *_values;
00799             }
00800         };
00801     }
00802 }
00803 
00804 #endif
00805 
00806 #endif

Generated on Fri Jun 19 13:39:40 2009 for BeeCrypt C++ by  doxygen 1.5.8