blob: c1b9674cb81fd532261b3f078f619ff1849634e6 [file]
/**
* default_valufact.c
* default value factory from which all others inherit
*/
#include <stdio.h>
#include "etch_global.h"
#include "etch_objects.h"
#include "etchexcp.h"
#include "etchutl.h"
#include "default_valufact.h"
etch_hashtable* new_vf_id_name_map(const int initialsize);
/**
* def_vf_impl_destructor
* destructor for def_vf_impl
*/
int def_vf_impl_destructor(def_vf_impl* impl)
{
impl_destroy_handler destroy = NULL; /* TODO ifdef sanity checks */
int result = verify_object((objmask*)impl, ETCHTYPEB_VALUEFACTIMP, CLASSID_DEF_VF_IMPL, NULL);
if (result == -1) return -1; /* specified object was not expected object */
/* invoke base class destructor */
destroy_instancedata(impl->base_impl, impl->base_type);
/* destroy this class' instance data */
//impl->mf_message_id_obj ->vtab->destroy(impl->mf_message_id_obj);
//impl->mf_in_reply_to_obj->vtab->destroy(impl->mf_in_reply_to_obj);
destroy_hashtable(impl->types, TRUE, TRUE);
destroy_hashtable(impl->fields, TRUE, TRUE);
/* destroy this object */
etch_free(impl);
return 0;
}
/**
* new_def_vf_impl()
* constructor for default vf instance data
*/
def_vf_impl* new_def_vf_impl(void* base_impl, const short base_type)
{
def_vf_impl* data = etch_malloc(sizeof(def_vf_impl), ETCHTYPEB_INSTANCEDATA);
memset(data, 0, sizeof(def_vf_impl));
data->obj_type = ETCHTYPEB_VALUEFACTIMP;
data->class_id = CLASSID_DEF_VF_IMPL;
data->base_impl = base_impl;
data->base_type = base_type;
data->destructor = def_vf_impl_destructor;
data->types = new_vf_id_name_map(ETCH_DEFVF_IDNMAP_DEFINITSIZE);
data->fields = new_vf_id_name_map(ETCH_DEFVF_IDNMAP_DEFINITSIZE);
//data->mf_message_id_obj = new_etch_field(L"_messageId");
//data->mf_in_reply_to_obj = new_etch_field(L"_inReplyTo");
//data->mf_message_id = data->mf_message_id_obj->value_ptr_to;
//data->mf_in_reply_to = data->mf_in_reply_to_obj->value_ptr_to;
return data;
}
/**
* defvf_add_type()
* adds a type to set of types
* @param type caller must supply a disposable type object
* @return the argument. If there is a collision with an id and name,
* the existing type is returned in place of the supplied type.
* @throws IllegalArgumentException (NULL return indicates as such)
*/
etch_type* defvf_add_type (etch_value_factory* vf, etch_type* type)
{
def_vf_impl* data = vf->impl; /* TODO unit test the defvf */
const int result = data->types->vtab->insert
(data->types->realtable, type, HASHSIZE_TYPE, NULL, 0, 0, 0);
return result == 0? type: NULL;
}
etch_type* defvf_get_type_by_id (etch_value_factory* vf, const unsigned id)
{
etch_hashitem hashbucket;
etch_hashitem* thisitem = &hashbucket;
def_vf_impl* data = vf->impl;
const int result = data->types->vtab->findh
(data->types->realtable, id, 0, &thisitem);
return result == 0? (etch_type*) thisitem->key: NULL;
}
etch_type* defvf_get_type_by_name (etch_value_factory* vf, const wchar_t* name)
{
def_vf_impl* data = vf->impl;
unsigned bytelen =(unsigned)(wcslen(name) + 1) * sizeof(wchar_t);
unsigned namehash = etchhash(name, bytelen, 0);
return defvf_get_type_by_id(vf, namehash);
}
etch_arraylist* defvf_get_types (etch_value_factory* vf)
{
def_vf_impl* data = vf->impl;
return get_map_keys(data->types);
}
/**
* defvf_add_field()
* adds a type to set of types
* @param type caller must supply a disposable field object
* @return the argument. If there is a collision with an id and name,
* the existing field is returned in place of the supplied field.
* @throws IllegalArgumentException (NULL return indicates as such)
*/
etch_field* defvf_add_field (etch_value_factory* vf, etch_field* field)
{
def_vf_impl* data = vf->impl; /* TODO unit test the defvf */
int result = data->fields->vtab->insert
(data->fields->realtable, field, HASHSIZE_FIELD, NULL, 0, 0, 0);
return result == 0? field: NULL;
}
etch_field* defvf_get_field_by_id (etch_value_factory* vf, const unsigned id)
{
etch_hashitem hashbucket;
etch_hashitem* thisitem = &hashbucket;
def_vf_impl* data = vf->impl;
const int result = data->fields->vtab->findh
(data->fields->realtable, id, 0, &thisitem);
return result == 0? (etch_field*) thisitem->key: NULL;
}
etch_field* defvf_get_field_by_name (etch_value_factory* vf, const wchar_t* name)
{
def_vf_impl* data = vf->impl;
unsigned bytelen =(unsigned)(wcslen(name) + 1) * sizeof(wchar_t);
unsigned namehash = etchhash(name, bytelen, 0);
return defvf_get_field_by_id(vf, namehash);
}
etch_arraylist* defvf_get_fields (etch_value_factory* vf)
{
def_vf_impl* data = vf->impl;
return get_map_keys(data->fields);
}
wchar_t* defvf_get_string_encoding (etch_value_factory* vf)
{
const static wchar_t* ETCH_STR_UTF8 = L"utf-8";
return clone_wchar(ETCH_STR_UTF8);
}
ETCH_STRUCTVALUE* defvf_export_custom_value (etch_value_factory* vf, etchobject* value)
{
return NULL;
}
etchobject* defvf_import_custom_value (etch_value_factory* vf, ETCH_STRUCTVALUE* svobj)
{
return NULL;
}
ETCH_TYPE* defvf_get_custom_struct_type (etch_value_factory* vf, unsigned class_id)
{
return NULL;
}
ETCH_CLASS* defvf_get_custom_type (etch_value_factory* vf, etch_type* t)
{
return NULL;
}
/**
* defvf_get_message_id() -- valuefactory.get_message_id() implementation.
*/
ETCH_INT64* defvf_get_message_id (etch_value_factory* vf, ETCH_MESSAGE* msgobj)
{
ETCH_INT64* idobj = NULL;
def_vf_impl* data = vf->impl;
// idobj = message_get(msgobj, data->mf_message_id);
return verifyx(idobj, ETCHTYPE_BOXED_INT64, EXCPTYPE_INTERNALERR);
}
/**
* defvf_set_message_id() -- valuefactory.set_message_id() implementation.
*/
int defvf_set_message_id (etch_value_factory* vf, ETCH_MESSAGE* msgobj, ETCH_INT64* idobj)
{
def_vf_impl* data = vf->impl;
// etch_type* keycopy = clone_type(data->mf_message_id);
etch_type* keycopy = 0; // *******
/* FYI this copy of the key is put to ETCH_MESSAGE* sent message, and gets
* freed in msgobj.destroy() (recall that message owns its memory).
* TODO clones should happen at a lower level */
message_put(msgobj, keycopy, idobj);
return is_exception(msgobj)? -1: 0;
}
/**
* defvf_get_in_reply_to() -- valuefactory.get_in_reply_to() implementation.
*/
ETCH_INT64* defvf_get_in_reply_to (etch_value_factory* vf, ETCH_MESSAGE* msgobj)
{
ETCH_INT64* idobj = NULL;
def_vf_impl* data = vf->impl;
//idobj = message_get(msgobj, data->mf_in_reply_to);
return verifyx(idobj, ETCHTYPE_BOXED_INT64, EXCPTYPE_INTERNALERR);
}
/**
* defvf_set_in_reply_to() -- valuefactory.set_message_id() implementation.
*/
int defvf_set_in_reply_to (etch_value_factory* vf, ETCH_MESSAGE* msgobj, ETCH_INT64* idobj)
{
def_vf_impl* data = vf->impl;
//etch_type* keycopy = clone_type(data->mf_in_reply_to);
etch_type* keycopy = 0; //*************
/* FYI this copy of the key is put to ETCH_MESSAGE* reply message, and gets
* freed in newobj.destroy(), since recall that message owns its memory.
* TODO clones should happen at a lower level */
message_put(msgobj, keycopy, idobj);
return is_exception(msgobj)? -1: 0;
}
/*
* value factory constructors/destructors
*/
/**
* new_default_value_factory()
* constructor for value factory implementation
*/
ETCH_VALUEFACTORY* new_default_value_factory()
{
ETCH_VALUEFACTORY* boxvf = NULL;
etch_value_factory* defvf = NULL;
i_value_factory* vtab = NULL;
const int VTABSIZE = sizeof(i_value_factory);
const int VTAB_KEY = ETCHTYPE_VTABLE_DEF_VF;
int result = 0;
boxvf = new_boxed_value_factory();
defvf = boxvf->value_ptr_to;
vtab = cache_find(VTAB_KEY,0);
if(!vtab)
{
vtab = new_vtable(defvf->vtab, VTABSIZE, ETCHTYPEB_VTABLE, CLASSID_DEF_VF_VTAB);
/* override four i_value_factory methods */
vtab->add_field = defvf_add_field;
vtab->add_type = defvf_add_type;
vtab->export_custom_value = defvf_export_custom_value;
vtab->get_custom_type = defvf_get_custom_type;
vtab->get_field_by_id = defvf_get_field_by_id;
vtab->get_field_by_name = defvf_get_field_by_name;
vtab->get_fields = defvf_get_fields;
vtab->get_in_reply_to = defvf_get_in_reply_to;
vtab->get_message_id = defvf_get_message_id;
vtab->get_string_encoding = defvf_get_string_encoding;
vtab->get_type_by_id = defvf_get_type_by_id;
vtab->get_type_by_name = defvf_get_type_by_name;
vtab->get_types = defvf_get_types;
vtab->import_custom_value = defvf_import_custom_value;
vtab->set_in_reply_to = defvf_set_in_reply_to;
vtab->set_message_id = defvf_set_message_id;
vtab->get_custom_struct_type = defvf_get_custom_struct_type;
vtab->vtab = defvf->vtab; /* chain parent vtab to override vtab */
cache_insert(VTAB_KEY, vtab, 0); /* cache the new vtab */
}
defvf->vtab = vtab; /* set override vtab */
defvf->impl = new_def_vf_impl(NULL, 0); /* create vf instance data */
return boxvf;
}
/**
* new_vf_id_name_map()
* return a hashtable configured as expected for a vf
*/
etch_hashtable* new_vf_id_name_map(const int initialsize)
{
etch_hashtable* map = new_etch_hashtable(initialsize);
if (map == NULL) return NULL;
map->content_type = ETCHHASHTABLE_CONTENT_OBJECT;
map->is_tracked_memory = TRUE;
map->is_readonly_keys = FALSE;
map->is_readonly_values = FALSE;
map->callback = NULL;
return map;
}