/* Starshatter: The Open Source Project Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. AUTHOR: John DiCamillo OVERVIEW ======== Implementation of the Dictionary class */ #ifndef NDEBUG #define DICT_CHECK(a, b) if ((a) == 0) throw b; #else #define DICT_CHECK(a, b) #endif const int CHAINS = 256; // +-------------------------------------------------------------------+ template Dictionary::Dictionary() : items(0) { init(); } template Dictionary::~Dictionary() { clear(); } // +-------------------------------------------------------------------+ template void Dictionary::init() { items = 0; memset(table, 0, CHAINS*sizeof(PTR)); } template void Dictionary::clear() { for (int i = 0; i < CHAINS; i++) { DictionaryCell* link = table[i]; while (link) { DictionaryCell* n = link->next; delete link; link = n; } } init(); } // +-------------------------------------------------------------------+ template T& Dictionary::operator[](const Text& key) { int idx = key.hash() % CHAINS; DictionaryCell* cell = table[idx]; if (cell == 0) { // empty chain items++; cell = new DictionaryCell(key); table[idx] = cell; return cell->value; } else { // search for key while (cell->next && cell->key != key) cell = cell->next; if (cell->key != key) { // not found in chain items++; cell->next = new DictionaryCell(key); return cell->next->value; } else { // found: return it! return cell->value; } } } // +-------------------------------------------------------------------+ template void Dictionary::insert(const Text& key, const T& val) { T& value = operator[](key); value = val; } // +-------------------------------------------------------------------+ template void Dictionary::remove(const Text& key) { int idx = key.hash() % CHAINS; DictionaryCell* cell = table[idx]; if (cell == 0) { // empty chain return; } else { // search for key while (cell->next && cell->key != key) cell = cell->next; if (cell->key != key) { // not found in chain return; } else { // found: remove it! if (table[idx] == cell) { table[idx] = cell->next; delete cell; } else { DictionaryCell* p = table[idx]; while (p->next != cell) p = p->next; p->next = cell->next; delete cell; } } } } // +-------------------------------------------------------------------+ template int Dictionary::contains(const Text& key) const { int idx = key.hash() % CHAINS; DictionaryCell* cell = table[idx]; if (cell != 0) { while (cell->next && cell->key != key) cell = cell->next; if (cell->key == key) return 1; } return 0; } // +-------------------------------------------------------------------+ template T Dictionary::find(const Text& key, T defval) const { int idx = key.hash() % CHAINS; DictionaryCell* cell = table[idx]; if (cell != 0) { while (cell->next && cell->key != key) cell = cell->next; if (cell->key == key) return cell->value; } return defval; } // +-------------------------------------------------------------------+ template DictionaryIter::DictionaryIter(Dictionary& d) : dict(&d), chain(0), here(0) { } template DictionaryIter::~DictionaryIter() { } // +-------------------------------------------------------------------+ template void DictionaryIter::reset() { chain = 0; here = 0; } // +-------------------------------------------------------------------+ template Text DictionaryIter::key() const { return here->key; } template T DictionaryIter::value() const { return here->value; } // +-------------------------------------------------------------------+ template int DictionaryIter::operator++() { forth(); int more = chain < CHAINS; return more; } // +-------------------------------------------------------------------+ template void DictionaryIter::forth() { if (here) { here = here->next; if (!here) // off the end of this chain chain++; } if (!here) { while (!dict->table[chain] && chain < CHAINS) chain++; if (chain < CHAINS) here = dict->table[chain]; else here = 0; } } // +-------------------------------------------------------------------+ template void DictionaryIter::attach(Dictionary& d) { dict = &d; reset(); } // +-------------------------------------------------------------------+ template Dictionary& DictionaryIter::container() { return *dict; }