First official checkin.
5 * Created by Jens Alfke on 8/20/09.
6 * Copyright 2009 Jens Alfke. All rights reserved.
7 * BSD-Licensed: See the file "LICENSE.txt" for details.
11 #include "Dictionary.h"
16 class Hash::IndexEntry {
18 IndexEntry (Key key, Hash::Value value =NULL)
23 Key key() const {return _key;}
24 HashCode hash() const {return _key.hash;}
25 Hash::Value value() const {return _key.bytes ?_value :NULL;}
26 void setValue (Hash::Value value) {_value = value;}
28 bool isAvailable() const {return _value == NULL;} // false if deleted
29 bool hasValue() const {return _key.bytes != NULL;}// false if deleted
30 bool operator==(const IndexEntry &e) const {return _key.hash==e._key.hash && _key.equals(e._key);}
31 bool operator!=(const IndexEntry &e) const {return ! (*this==e);}
33 void markDeleted() {_key.bytes = NULL; _value = (Hash::Value)-1;}
34 void markEmpty() {_key.bytes = NULL; _value = NULL;}
37 Key _key; // bytes will be NULL if empty or deleted
38 Hash::Value _value; // NULL if empty, -1 if deleted
42 Hash::Hash (int capacity)
44 _tableSize( Dictionary::choosePowerOfTwoSize(capacity) ),
45 _table( (IndexEntry*) calloc(_tableSize,sizeof(IndexEntry)) )
52 Hash::IndexEntry& Hash::_find (Key key) const {
54 IndexEntry newEntry(k);
55 int index = newEntry.hash() % _tableSize;
56 IndexEntry *found = &_table[index];
58 while (!found->isAvailable() && (!found->hasValue() || *found != newEntry)) {
59 index = (index + ++probe) % _tableSize;
60 found = &_table[index];
65 Hash::IndexEntry& Hash::_findForPut (const Hash::IndexEntry &newEntry) {
66 int index = newEntry.hash() % _tableSize;
67 IndexEntry *found = &_table[index];
69 while (found->hasValue() && *found != newEntry) {
70 index = (index + ++probe) % _tableSize;
71 found = &_table[index];
76 Hash::Value Hash::get(Key key) const {
77 return _find(key).value();
80 void Hash::put(Key key, Hash::Value value) {
81 IndexEntry newEntry = IndexEntry(Key(key),value);
82 IndexEntry &found = _findForPut(newEntry);
84 found.setValue(value);
88 if (_count/(float)_tableSize > Dictionary::kMaxLoadFactor)
89 _resize(2*_tableSize);
93 bool Hash::remove(Key key) {
94 IndexEntry &entry = _find(key);
99 if (_count/(float)_tableSize < Dictionary::kMinLoadFactor)
100 _resize(_tableSize/2);
104 void Hash::removeAll() {
105 memset(_table, 0, _tableSize*sizeof(*_table));
109 void Hash::dump() const {
110 for (int index=0; index<_tableSize; index++)
111 if (_table[index].hasValue()) {
112 Blob key = _table[index].key();
113 printf("%3i: %*s -> %p\n",
114 index, (int)key.length,(const char*)key.bytes, _table[index].value());
119 void Hash::_resize(int newSize) {
120 newSize = std::max(newSize, Dictionary::kMinSize);
121 if (newSize != _tableSize) {
122 IndexEntry* oldTable = _table;
123 int oldTableSize = _tableSize;
124 _tableSize = newSize;
125 _table = (IndexEntry*) calloc(_tableSize,sizeof(IndexEntry));
127 // Add existing entries to new table:
128 for (int index=0; index<oldTableSize; index++) {
129 IndexEntry &entry = oldTable[index];
131 _findForPut(entry) = entry;
137 Hash::Iterator::Iterator (const Hash *hash)
138 :_entry(hash->_table-1), _end(hash->_table+hash->_tableSize)
143 Hash::Iterator::Iterator (const Hash &hash)
144 :_entry(hash._table-1), _end(hash._table+hash._tableSize)
149 bool Hash::Iterator::next() {
150 while (++_entry < _end) {
151 if (_entry->hasValue())
157 Key Hash::Iterator::key() const {return _entry->key();}
158 Hash::Value Hash::Iterator::value() const {return _entry->value();}