jbm: it compiles... but bombs in unit tests
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"
17 class Hash::IndexEntry {
19 IndexEntry (Key key, Hash::Value value =NULL)
24 const Key& key() const {return _key;}
25 HashCode hash() const {return _key.hash;}
26 Hash::Value value() const {return _key.bytes ?_value :NULL;}
27 void setValue (Hash::Value value) {_value = value;}
29 bool isAvailable() const {return _value == NULL;} // false if deleted
30 bool hasValue() const {return _key.bytes != NULL;}// false if deleted
31 bool operator==(const IndexEntry &e) const {return _key.hash==e._key.hash && _key.equals(e._key);}
32 bool operator!=(const IndexEntry &e) const {return ! (*this==e);}
34 void markDeleted() {_key.bytes = NULL; _value = (Hash::Value)-1;}
35 void markEmpty() {_key.bytes = NULL; _value = NULL;}
38 Key _key; // bytes will be NULL if empty or deleted
39 Hash::Value _value; // NULL if empty, -1 if deleted
43 Hash::Hash (int capacity)
45 _tableSize( Dictionary::choosePowerOfTwoSize(capacity) ),
46 _table( (IndexEntry*) calloc(_tableSize,sizeof(IndexEntry)) )
53 Hash::IndexEntry& Hash::_find (Key key) const {
54 IndexEntry newEntry(key);
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,value);
82 IndexEntry &found = _findForPut(newEntry);
84 found.setValue(value);
88 if (_count/(float)_tableSize > Dictionary::kMaxLoadFactor)
89 _resize(2*_tableSize);
93 Hash::Value Hash::remove(Key key) {
94 IndexEntry &entry = _find(key);
95 Value formerValue = entry.value();
100 if (_count/(float)_tableSize < Dictionary::kMinLoadFactor)
101 _resize(_tableSize/2);
105 void Hash::removeAll() {
106 memset(_table, 0, _tableSize*sizeof(*_table));
110 void Hash::dump() const {
111 for (int index=0; index<_tableSize; index++)
112 if (_table[index].hasValue()) {
113 const Key &key = _table[index].key();
114 ::printf("%3i: %*s -> %p\n",
115 index, (int)key.length,(const char*)key.bytes, _table[index].value());
120 void Hash::_resize(int newSize) {
121 newSize = std::max(newSize, Dictionary::kMinSize);
122 if (newSize != _tableSize) {
123 IndexEntry* oldTable = _table;
124 int oldTableSize = _tableSize;
125 _tableSize = newSize;
126 _table = (IndexEntry*) calloc(_tableSize,sizeof(IndexEntry));
128 // Add existing entries to new table:
129 for (int index=0; index<oldTableSize; index++) {
130 IndexEntry &entry = oldTable[index];
132 _findForPut(entry) = entry;
138 Hash::Iterator::Iterator (const Hash *hash)
139 :_entry(hash->_table-1), _end(hash->_table+hash->_tableSize)
144 Hash::Iterator::Iterator (const Hash &hash)
145 :_entry(hash._table-1), _end(hash._table+hash._tableSize)
150 bool Hash::Iterator::next() {
151 while (++_entry < _end) {
152 if (_entry->hasValue())
158 Key Hash::Iterator::key() const {return _entry->key();}
159 Hash::Value Hash::Iterator::value() const {return _entry->value();}