#include "object.h" #include "type.h" #include #include #include #include #include #include FX_TYPE_CLASS_DEFINITION_BEGIN(fx_object) FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) FX_INTERFACE_ENTRY(to_string) = NULL; FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT) FX_TYPE_CLASS_DEFINITION_END(fx_object) FX_TYPE_DEFINITION_BEGIN(fx_object) FX_TYPE_ID(0x45f15a2c, 0x6831, 0x4bef, 0xb350, 0x15c650679211); FX_TYPE_CLASS(fx_object_class); FX_TYPE_DEFINITION_END(fx_object) fx_result fx_object_instantiate( struct fx_type_registration *type, struct _fx_object **out_object) { struct _fx_object *out = malloc(type->r_instance_size); if (!out) { return FX_RESULT_ERR(NO_MEMORY); } memset(out, 0x0, type->r_instance_size); out->obj_magic = FX_OBJECT_MAGIC; out->obj_type = type; out->obj_ref = 1; struct fx_queue_entry *entry = fx_queue_first(&type->r_class_hierarchy); while (entry) { struct fx_type_component *comp = fx_unbox(struct fx_type_component, entry, c_entry); const struct fx_type_info *class_info = comp->c_type->r_info; void *private_data = (char *)out + comp->c_instance_private_data_offset; if (class_info->t_instance_init) { class_info->t_instance_init(out, private_data); } if (comp->c_type == type) { out->obj_main_priv_offset = comp->c_instance_private_data_offset; } entry = fx_queue_next(entry); } *out_object = out; return FX_RESULT_SUCCESS; } struct _fx_object *fx_object_create(fx_type type) { struct fx_type_registration *type_reg = fx_type_get_registration(type); if (!type_reg) { return NULL; } struct _fx_object *out = NULL; fx_result result = fx_object_instantiate(type_reg, &out); if (fx_result_is_error(result)) { fx_error_discard(result); return NULL; } return out; } void fx_object_to_string(const struct _fx_object *p, fx_stream *out) { FX_CLASS_DISPATCH_VIRTUAL_V(fx_object, FX_TYPE_OBJECT, to_string, p, out); fx_stream_write_fmt(out, NULL, "<%s@%p>", p->obj_type->r_info->t_name, p); } bool fx_object_is_type(const struct _fx_object *p, fx_type type) { if (fx_type_id_compare(&p->obj_type->r_info->t_id, type) == 0) { return true; } struct fx_type_component *comp = fx_type_get_component(&p->obj_type->r_components, type); return comp != NULL; } void *fx_object_get_private(const struct _fx_object *object, fx_type type) { if (!object) { return NULL; } assert(object->obj_magic == FX_OBJECT_MAGIC); if (fx_type_id_compare(&object->obj_type->r_info->t_id, type) == 0) { return (char *)object + object->obj_main_priv_offset; } struct fx_type_component *comp = fx_type_get_component(&object->obj_type->r_components, type); if (!comp) { return NULL; } return (char *)object + comp->c_instance_private_data_offset; } void *fx_object_get_protected(const struct _fx_object *object, fx_type type) { if (!object) { return NULL; } assert(object->obj_magic == FX_OBJECT_MAGIC); struct fx_type_component *comp = fx_type_get_component(&object->obj_type->r_components, type); if (!comp) { return NULL; } return (char *)object + comp->c_instance_protected_data_offset; } void *fx_object_get_interface(const struct _fx_object *object, fx_type type) { if (!object) { return NULL; } assert(object->obj_magic == FX_OBJECT_MAGIC); return fx_class_get_interface(object->obj_type->r_class, type); } enum fx_status fx_object_get_data( const struct _fx_object *object, fx_type type, void **priv, void **prot, void **iface) { if (!object) { return FX_ERR_INVALID_ARGUMENT; } assert(object->obj_magic == FX_OBJECT_MAGIC); struct fx_type_component *comp = fx_type_get_component(&object->obj_type->r_components, type); if (!comp) { return FX_ERR_INVALID_ARGUMENT; } if (priv) { *priv = (char *)object + comp->c_instance_private_data_offset; } if (prot) { *prot = (char *)object + comp->c_instance_protected_data_offset; } if (iface) { *iface = (char *)object->obj_type->r_class + comp->c_class_data_offset; } return FX_SUCCESS; } struct _fx_object *fx_object_ref(struct _fx_object *p) { p->obj_ref++; return p; } void fx_object_unref(struct _fx_object *p) { if (p->obj_ref > 1) { p->obj_ref--; return; } p->obj_ref = 0; const struct fx_type_registration *type = p->obj_type; struct fx_queue_entry *cur = fx_queue_last(&type->r_class_hierarchy); while (cur) { struct fx_type_component *comp = fx_unbox(struct fx_type_component, cur, c_entry); const struct fx_type_info *class_info = comp->c_type->r_info; void *private_data = (char *)p + comp->c_instance_private_data_offset; if (class_info->t_instance_fini) { class_info->t_instance_fini(p, private_data); } cur = fx_queue_prev(cur); } p->obj_magic = 0; p->obj_type = NULL; free(p); } struct _fx_object *fx_object_make_rvalue(struct _fx_object *p) { p->obj_ref = 0; return p; }