#include <u.h>
#include <libc.h>
#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);
}
|