//*****************************************************************************
//
// auxiliary.c
//
// when installing a new module, it is often required that extra data be
// stored in the basic datastructures (rooms, characters, objects, etc...).
// However, we want to keep the modules as removed from the core of the MUD
// as possible, and having to put in extra data into the basic datastructures
// seems like an undesirable thing. Provided below are a set of functions that
// can be used for "installing" new data into the datastructures without having
// to directly edit the code.
//
//*****************************************************************************
#include "mud.h"
#include "utils.h"
#include "storage.h"
#include "auxiliary.h"
//*****************************************************************************
//
// local variables, datastructures, and functions
//
//*****************************************************************************
//
// the function sets used for loading and saving
// auxiliary functions on our datatypes
HASHTABLE *auxiliary_manip_funcs = NULL;
struct auxiliary_functions {
bitvector_t aux_type;
bool is_py;
void *(* new)(void);
void (* delete)(void *data);
void (* copyTo)(void *from, void *to);
void *(* copy)(void *data);
STORAGE_SET *(* store)(void *data);
void *(* read)(STORAGE_SET *set);
};
//*****************************************************************************
//
// implementation of auxiliary.h
// documentation in auxiliary.h
//
//*****************************************************************************
void init_auxiliaries() {
auxiliary_manip_funcs = newHashtable();
}
AUXILIARY_FUNCS *
newAuxiliaryFuncs(bitvector_t aux_type, void *new, void *delete,
void *copyTo, void *copy, void *store, void *read) {
AUXILIARY_FUNCS *newfuncs = malloc(sizeof(AUXILIARY_FUNCS));
newfuncs->is_py = FALSE;
newfuncs->aux_type = aux_type;
newfuncs->new = new;
newfuncs->delete = delete;
newfuncs->copyTo = copyTo;
newfuncs->copy = copy;
newfuncs->store = store;
newfuncs->read = read;
return newfuncs;
}
void
deleteAuxiliaryFuncs(AUXILIARY_FUNCS *funcs) {
free(funcs);
}
void auxiliaryFuncSetIsPy(AUXILIARY_FUNCS *funcs, bool val) {
funcs->is_py = val;
}
void
auxiliariesInstall(const char *name, AUXILIARY_FUNCS *funcs) {
hashPut(auxiliary_manip_funcs, name, funcs);
}
void
auxiliariesUninstall(const char *name) {
AUXILIARY_FUNCS *funcs = hashRemove(auxiliary_manip_funcs, name);
if(funcs != NULL)
deleteAuxiliaryFuncs(funcs);
}
AUXILIARY_FUNCS *
auxiliariesGetFuncs(const char *name) {
return hashGet(auxiliary_manip_funcs, name);
}
HASHTABLE *
newAuxiliaryData(bitvector_t aux_type) {
HASHTABLE *data = newHashtable();
HASH_ITERATOR *hash_i = newHashIterator(auxiliary_manip_funcs);
AUXILIARY_FUNCS *funcs = NULL;
const char *name = NULL;
ITERATE_HASH(name, funcs, hash_i) {
if(IS_SET(funcs->aux_type, aux_type)) {
// are we dealing with python data or not?
if(!funcs->is_py)
hashPut(data, name, funcs->new());
else {
// recast the new function
void *(* new)(const char *) = (void *)funcs->new;
hashPut(data, name, new(name));
}
}
} deleteHashIterator(hash_i);
return data;
}
void
auxiliaryEnsureDataComplete(HASHTABLE *data, bitvector_t aux_type) {
HASH_ITERATOR *hash_i = newHashIterator(auxiliary_manip_funcs);
AUXILIARY_FUNCS *funcs = NULL;
const char *name = NULL;
ITERATE_HASH(name, funcs, hash_i) {
if(IS_SET(funcs->aux_type, aux_type) && !hashGet(data, name)) {
// are we dealing with python data or not?
if(!funcs->is_py)
hashPut(data, name, funcs->new());
else {
// recast the new function
void *(* new)(const char *) = (void *)funcs->new;
hashPut(data, name, new(name));
}
}
} deleteHashIterator(hash_i);
}
void
deleteAuxiliaryData(HASHTABLE *data) {
// go across all of the data in the hashtable, and delete it
AUXILIARY_FUNCS *funcs = NULL;
HASH_ITERATOR *hash_i = newHashIterator(data);
void *entry = NULL;
const char *name = NULL;
ITERATE_HASH(name, entry, hash_i) {
funcs = auxiliariesGetFuncs(name);
funcs->delete(entry);
} deleteHashIterator(hash_i);
deleteHashtable(data);
}
STORAGE_SET *
auxiliaryDataStore(HASHTABLE *data) {
STORAGE_SET *set = new_storage_set();
AUXILIARY_FUNCS *funcs = NULL;
HASH_ITERATOR *hash_i = newHashIterator(data);
void *entry = NULL;
const char *name = NULL;
ITERATE_HASH(name, entry, hash_i) {
funcs = auxiliariesGetFuncs(name);
if(funcs->store)
store_set(set, name, funcs->store(entry));
} deleteHashIterator(hash_i);
return set;
}
HASHTABLE *
auxiliaryDataRead(STORAGE_SET *set, bitvector_t aux_type) {
HASHTABLE *data = newHashtable();
HASH_ITERATOR *hash_i = newHashIterator(auxiliary_manip_funcs);
AUXILIARY_FUNCS *funcs = NULL;
const char *name = NULL;
ITERATE_HASH(name, funcs, hash_i) {
if(!IS_SET(funcs->aux_type, aux_type))
continue;
// are we dealing with python data or not?
if(!funcs->is_py && funcs->read)
hashPut(data, name, funcs->read(read_set(set, name)));
else if(funcs->read) {
// recast the read function
void *(* read)(const char *, STORAGE_SET *) = (void *)funcs->read;
hashPut(data, name, read(name, read_set(set, name)));
}
// are we dealing with python data or not?
else if(!funcs->is_py)
hashPut(data, name, funcs->new());
else {
// recast the new function
void *(* new)(const char *) = (void *)funcs->new;
hashPut(data, name, new(name));
}
} deleteHashIterator(hash_i);
return data;
}
void
auxiliaryDataCopyTo(HASHTABLE *from, HASHTABLE *to) {
AUXILIARY_FUNCS *funcs = NULL;
HASH_ITERATOR *hash_i = NULL;
void *entry = NULL;
const char *name = NULL;
// first, delete all of the old data
if(hashSize(to) > 0) {
hash_i = newHashIterator(to);
ITERATE_HASH(name, entry, hash_i) {
funcs = auxiliariesGetFuncs(name);
funcs->delete(entry);
} deleteHashIterator(hash_i);
}
// now, copy in all of the new data
if(hashSize(from) > 0) {
hash_i = newHashIterator(from);
ITERATE_HASH(name, entry, hash_i) {
funcs = auxiliariesGetFuncs(name);
hashPut(to, name, funcs->copy(entry));
} deleteHashIterator(hash_i);
}
}
HASHTABLE *
auxiliaryDataCopy(HASHTABLE *data) {
HASHTABLE *newdata = newHashtableSize(hashSize(data));
auxiliaryDataCopyTo(data, newdata);
return newdata;
}