#include #include #include "common.h" #include "debug.h" #include "collection.h" #include "function.h" #include "array.h" #include "set.h" #include "dictionary.h" enum { DEBUG_PAIR = false }; struct Dictionary { collectionhash hash; collectionisequal isequal; Set *elements; }; typedef struct Pair { void *key; void *value; Dictionary *container; } Pair; Pair *pair_new(void *key, void *value, Dictionary *container) { Pair *result = (Pair *)emalloc_fs(sizeof(Pair)); result->key = key; result->value = value; result->container = container; return result; } uint pair_hash(void *p) { Pair *self = (Pair *)p; return self->container->hash(self->key); } bool pair_isequal(void *p1, void *p2) { Pair *self = (Pair *)p1; Pair *object = (Pair *)p2; return self->container->isequal(self->key, object->key); } enum { DEBUG_DICTIONARY = false }; Dictionary *dictionary_new(collectionisequal isequal, collectionhash hash) { Dictionary *result = (Dictionary *)emalloc_fs(sizeof(Dictionary)); result->hash = hash; result->isequal = isequal; result->elements = set_new(pair_isequal, pair_hash); return result; } void dictionary_free(Dictionary *self) { if(self == nil) { return; } set_free_with(self->elements, free); free(self); } typedef struct DictionaryFreeWithData { functionunary free_key; functionunary free_value; } DictionaryFreeWithData; collection_do_ret dictionary_free_with_each(void *p, void *arg) { Pair *pair = (Pair *)p; DictionaryFreeWithData *data = (DictionaryFreeWithData *)arg; if(data->free_key != nil) { data->free_key(pair->key); } if(data->free_value != nil) { data->free_value(pair->value); } return COLLECTION_DO_CONTINUE; } void dictionary_free_with(Dictionary *self, functionunary free_key, functionunary free_value) { DictionaryFreeWithData data = (DictionaryFreeWithData) {free_key, free_value}; set_do(self->elements, dictionary_free_with_each, &data); dictionary_free(self); } uint dictionary_size(Dictionary *self) { return set_size(self->elements); } bool dictionary_add(Dictionary *self, void *key, void *value) { Pair temp = (Pair) {key, value, self}; Pair *item = &temp; assert_valid(self); if(set_find(self->elements, &item)) { item->value = value; return false; } item = pair_new(key, value, self); set_add(self->elements, item); return true; } bool dictionary_remove(Dictionary *self, void *key) { Pair p = (Pair) {key, nil, self}; assert_valid(self); return set_remove(self->elements, &p); } void *dictionary_at(Dictionary *self, void *key) { bool result; void *value; assert_valid(self); result = dictionary_get_key_value(self, &key, &value); assert(result); return value; } bool dictionary_get_key_value(Dictionary *self, void **key, void **value) { Pair p = (Pair) {nil, nil, self}; Pair *result = &p; assert_valid(key); assert_valid(self); result->key = *key; if(!set_find(self->elements, &result)) { return false; } *key = result->key; if(value != nil) { *value = result->value; } return true; } bool dictionary_get(Dictionary *self, void *key, void **value) { return dictionary_get_key_value(self, &key, value); } bool dictionary_includes(Dictionary *self, void *key) { return dictionary_get(self, key, nil); }