| /** | |
| * 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; | |
| } | |