00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stlib/Dictionary.h>
00025 #include <stlib/Association.h>
00026 #include <stlib/Array.h>
00027 #include <stlib/KAVIterator.h>
00028 #include <stlib/String.h>
00029 #include <stlib/Visitor.h>
00030
00031 #include <stlib/KeyNotFoundError.h>
00032 #include <stlib/ValueNotFoundError.h>
00033 #include <stlib/SOOBoundsError.h>
00034
00035 Dictionary::Dictionary(int length)
00036 : Set(length)
00037 {
00038 }
00039
00040
00041 String *Dictionary::className(void) const
00042 {
00043 return new String("Dictionary");
00044 }
00045
00046
00047 Object *Dictionary::at(Object *key)
00048 {
00049 long index;
00050 Association *obj;
00051
00052 index = findKeyOrNil(key);
00053 obj = (Association *) content->at(index);
00054 if (obj == nil)
00055 (new KeyNotFoundError(__PRETTY_FUNCTION__, key))->raiseFrom(this);
00056 return obj->value();
00057 }
00058
00059 Object *Dictionary::at(Object *key, Object *ifAbsentValue)
00060 {
00061 long index;
00062 Association *obj;
00063
00064 index = findKeyOrNil(key);
00065 obj = (Association *) content->at(index);
00066 if (obj == nil)
00067 return ifAbsentValue;
00068 return obj->value();
00069 }
00070
00071 Object *Dictionary::at(const char *key) {
00072 return at(new String(key));
00073 }
00074
00075 Object *Dictionary::at(const char* key, const char *ifAbsentValue) {
00076 return at(new String(key), (ifAbsentValue == nil ? nil : new String(ifAbsentValue)));
00077 }
00078
00079 void Dictionary::put(Object *key, Object *value)
00080 {
00081 long index;
00082 Association *element;
00083
00084 if (key == nil)
00085 (new SubscriptOutOfBoundsError(__PRETTY_FUNCTION__, 0))->raiseFrom(this);
00086 index = findKeyOrNil(key);
00087 element = (Association *) content->at(index);
00088 if (element == nil) atNewIndexPut(index, new Association(key, value));
00089 else element->value(value);
00090 }
00091
00092 void Dictionary::put(const char* key, Object* value) {
00093 put(new String(key), value);
00094 }
00095
00096 void Dictionary::put(const char* key, const char* value) {
00097 put(new String(key), new String(value));
00098 }
00099
00100 Object *Dictionary::keyAtValue(Object *value)
00101 {
00102 for (KeysAndValuesIterator i(this); !i.finished(); i.next()) {
00103 if (i.value()->isEqual(value))
00104 return i.key();
00105 }
00106 (new ValueNotFoundError(__PRETTY_FUNCTION__, value))->raiseFrom(this);
00107 }
00108
00109 Object *Dictionary::keyAtValue(Object *value, Object *ifAbsentKey)
00110 {
00111 Object *obj;
00112
00113 try {
00114 obj = keyAtValue(value);
00115 }
00116 catch (ValueNotFoundError *ex) {
00117 obj = ifAbsentKey;
00118 }
00119 return obj;
00120 }
00121
00122
00123 void Dictionary::add(Object *assoc)
00124 {
00125 long index;
00126 Object *assocKey;
00127 Association *element;
00128
00129 if (!assoc->isAssociation() ||
00130 (assocKey = ((Association *) assoc)->key()) == nil)
00131 (new SubscriptOutOfBoundsError(__PRETTY_FUNCTION__, 0))->raiseFrom(this);
00132 index = findKeyOrNil(assocKey);
00133 element = (Association *) content->at(index);
00134 if (element == nil) atNewIndexPut(index, assoc);
00135 else element->value(((Association *)assoc)->value());
00136 }
00137
00138
00139 Object *Dictionary::copy(void)
00140 {
00141 return new Dictionary(*this);
00142 }
00143
00144 Object *Dictionary::copyEmpty(long size)
00145 {
00146 return new Dictionary(size);
00147 }
00148
00149
00150 KeysAndValuesIterator *Dictionary::keysAndValuesIterator(void) const
00151 {
00152 return new KeysAndValuesIterator(this);
00153 }
00154
00155
00156 Object *Dictionary::remove(Object *)
00157 {
00158 shouldNotImplement(new String(__PRETTY_FUNCTION__));
00159 return nil;
00160 }
00161
00162 Object *Dictionary::removeKey(Object *key)
00163 {
00164 long index;
00165 Association *element;
00166
00167 index = findKey(key);
00168 element = (Association *) content->at(index);
00169 content->put(index, nil);
00170 tally = tally - 1;
00171 fixCollisionsFrom(index);
00172 return element->value();
00173 }
00174
00175
00176 bool Dictionary::includes(Object *obj)
00177 {
00178 return Collection::includes(obj);
00179 }
00180
00181 bool Dictionary::includesKey(Object *key)
00182 {
00183 return content->at(findKeyOrNil(key)) != nil;
00184 }
00185
00186
00187 void Dictionary::visitBy(Visitor *visitor)
00188 {
00189 visitor->visitDictionary(this);
00190 }
00191
00192
00193 void Dictionary::changeCapacity(long newCapacity)
00194 {
00195 Array *oldContent;
00196 Iterator *i;
00197
00198 oldContent = content;
00199 content = new Array(newCapacity);
00200 tally = 0;
00201 for (i = oldContent->iterator(); !i->finished(); i->next()) {
00202 if (i->value() != nil)
00203 noCheckAdd((Association *) i->value());
00204 }
00205 delete i;
00206 delete oldContent;
00207 }
00208
00209 int Dictionary::findKey(Object *key)
00210 {
00211 int index;
00212
00213 index = findKeyOrNil(key);
00214 if (content->at(index) == nil)
00215 (new KeyNotFoundError(__PRETTY_FUNCTION__, key))->raiseFrom(this);
00216 return index;
00217 }
00218
00219 int Dictionary::findKeyOrNil(Object *key)
00220 {
00221 int pass, length = capacity();
00222 Association *elem;
00223 int index;
00224
00225 index = key->hash() % length;
00226
00227 if (index < 0) index = length + index;
00228 pass = 1;
00229 while ((elem = (Association *) content->at(index)) != nil &&
00230 !elem->key()->isEqual(key)) {
00231 index++;
00232 if (index >= length) {
00233 index = 0;
00234 pass++;
00235 if (pass > 2) {
00236 grow();
00237 return findKeyOrNil(key);
00238 }
00239 }
00240 }
00241 return index;
00242 }
00243
00244 void Dictionary::fixCollisionsFrom(int oldIndex)
00245 {
00246 int length, nextIndex;
00247 Association *nextObject = nil;
00248
00249 length = capacity();
00250 nextIndex = oldIndex;
00251 do {
00252 if (nextIndex != oldIndex) {
00253 content->put(nextIndex, nextObject);
00254 content->put(oldIndex, nil);
00255 }
00256 oldIndex = (oldIndex + 1) % length;
00257 nextObject = (Association *) content->at(oldIndex);
00258 if (nextObject != nil)
00259 nextIndex = findKeyOrNil(nextObject->key());
00260 } while (nextObject != nil);
00261 }
00262
00263 void Dictionary::noCheckAdd(Association *object)
00264 {
00265 content->put(findKeyOrNil(object->key()), object);
00266 tally = tally + 1;
00267 }