#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Dictionary.h" #include "Class.h" #include "DictHashTab.h" //---- Dictionary -------------------------------------------------------------- NewMetaImpl(Dictionary,Container, (TP(ht))); Object *Dictionary::ignore= 0; Dictionary::Dictionary(int initCapacity) : Container() { Init(initCapacity); } Dictionary::~Dictionary() { SafeDelete(ht); } Object *Dictionary::Clone() { Object *key, *value; Dictionary *clone= (Dictionary*) New(); DictionaryIterator next(this); while (key= next()) { value= next.GetValue(); clone->PutAtKeyIfAbsent(value, key); } return clone; } void Dictionary::InitNew() { Container::InitNew(); Init(cContainerInitCap); } void Dictionary::FreeAll() { DictionaryIterator next(this); Object *key, *value; CheckForIterator("FreeAll"); while (key= next()) { key->FreeAll(); value= next.GetValue(); value->FreeAll(); SafeDelete(key); SafeDelete(value); } Empty(cContainerInitCap); } int Dictionary::Capacity() { return ht->Capacity(); } void Dictionary::Empty(int newCapacity) { CheckForIterator("Empty"); ht->Empty(newCapacity); Changed(); } void Dictionary::FreeValues() { DictionaryIterator it(this); Object *value; CheckForIterator("FreeValues"); while (value= it.NextValue()) SafeDelete(value); Empty(cContainerInitCap); } void Dictionary::FreeAllValues() { DictionaryIterator it(this); Object *value; CheckForIterator("FreeAllValues"); while (value= it.NextValue()) { value->FreeAll(); SafeDelete(value); } Empty(cContainerInitCap); } Object *Dictionary::PutAtKeyIfAbsent(Object *value, Object *key) { if (IsArgNull("PutAtKeyIfAbsent(value)", value) || IsArgNull("PutAtKeyIfAbsent(key)", key)) return value; CheckForIterator("AddAtKey"); Object *val= (Object*) ht->AddAt(value, key, FALSE); if (! val) Changed(); return val; } Object *Dictionary::PutAtKey(Object *value, Object *key) { if (IsArgNull("PutAtKey(value)", value) || IsArgNull("PutAtKey(key)", key)) return value; CheckForIterator("AddAtKey"); Object *oldValue= (Object*) ht->AddAt(value, key, TRUE); if (oldValue != value) Changed(); return oldValue; } Object *Dictionary::RemoveKey(Object *key, Object *&value) { if (IsArgNull("RemoveKey", key)) return 0; CheckForIterator("RemoveKey"); Object *removedKey= (Object*) ht->RemoveKey(key, (void **) &value, eEqValue); if (removedKey) Changed(); return removedKey; } Iterator *Dictionary::MakeIterator(bool, void *placement) { return new(placement) DictionaryIterator(this); } Object *Dictionary::AtKey(Object *key) { return (Object*) ht->AtKey(key, eEqValue); } OStream &Dictionary::PrintOn(OStream &os) { Object *key; DictionaryIterator next(this); Container::PrintOn(os); os NL; while (key= next()) os << key SP << next.GetValue() NL; return os NL; } IStream &Dictionary::ReadFrom(IStream &is) { Object *key, *value; int nread, sz; Container::ReadFrom(is); nread= 0; sz= size; size= 0; while (nread < sz) { is >> key >> value; nread++; PutAtKey(value, key); } return is; } void Dictionary::Init(int initCapacity) { ht= new DictHashTab( initCapacity, &ContainerTypes::pEqual, &ContainerTypes::pHash, &size); } Dictionary::Dictionary(Dictionary *) : Container() { ht= 0; } //---- DictionaryIterator ------------------------------------------------------ DictionaryIterator::DictionaryIterator(Dictionary *adt) { dt= adt; pix= 0; ht= 0; } DictionaryIterator::~DictionaryIterator() { Terminate(); } void DictionaryIterator::Reset() { Iterator::Reset(); pix= 0; } Object *DictionaryIterator::operator()() { return NextIndex(); } Object *DictionaryIterator::NextValue() { if (NextIndex()) return (Object*) ht->ValueAt(pix); return 0; } Object *DictionaryIterator::NextKey() { return NextIndex(); } Object *DictionaryIterator::GetValue() { if (IsActive()) return (Object*) ht->ValueAt(pix); return 0; } Container *DictionaryIterator::GetContainer() { return dt; } Object *DictionaryIterator::NextIndex() { if (! Activated()) { if (Activate()) { ht= dt->ht; pix= ht->GetInitialIndex(); } } if (! Terminated()) { Object *op= (Object*) ht->AtNextIndex(pix); if (op == 0) Terminate(); return op; } return 0; }