147 lines
3.5 KiB
C
147 lines
3.5 KiB
C
|
|
#include "object.h"
|
||
|
|
|
||
|
|
#include "type.h"
|
||
|
|
|
||
|
|
#include <blue/core/thread.h>
|
||
|
|
#include <blue/object/class.h>
|
||
|
|
#include <blue/object/macros.h>
|
||
|
|
#include <blue/object/object.h>
|
||
|
|
|
||
|
|
B_TYPE_CLASS_DEFINITION_BEGIN(b_object)
|
||
|
|
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
|
||
|
|
B_INTERFACE_ENTRY(to_string) = NULL;
|
||
|
|
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
|
||
|
|
B_TYPE_CLASS_DEFINITION_END(b_object)
|
||
|
|
|
||
|
|
B_TYPE_DEFINITION_BEGIN(b_object)
|
||
|
|
B_TYPE_ID(0x45f15a2c, 0x6831, 0x4bef, 0xb350, 0x15c650679211);
|
||
|
|
B_TYPE_CLASS(b_object_class);
|
||
|
|
B_TYPE_DEFINITION_END(b_object)
|
||
|
|
|
||
|
|
b_result b_object_instantiate(
|
||
|
|
struct b_type_registration *type, struct _b_object **out_object)
|
||
|
|
{
|
||
|
|
struct _b_object *out = malloc(type->r_instance_size);
|
||
|
|
if (!out) {
|
||
|
|
return B_RESULT_ERR(NO_MEMORY);
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(out, 0x0, type->r_instance_size);
|
||
|
|
|
||
|
|
out->obj_magic = B_OBJECT_MAGIC;
|
||
|
|
out->obj_type = type;
|
||
|
|
out->obj_ref = 1;
|
||
|
|
|
||
|
|
b_queue_iterator q_it;
|
||
|
|
b_queue_foreach (&q_it, &type->r_class_hierarchy) {
|
||
|
|
struct b_type_component *comp
|
||
|
|
= b_unbox(struct b_type_component, q_it.entry, c_entry);
|
||
|
|
const struct b_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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*out_object = out;
|
||
|
|
return B_RESULT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct _b_object *b_object_create(b_type type)
|
||
|
|
{
|
||
|
|
struct b_type_registration *type_reg = b_type_get_registration(type);
|
||
|
|
if (!type_reg) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct _b_object *out = NULL;
|
||
|
|
b_result result = b_object_instantiate(type_reg, &out);
|
||
|
|
if (b_result_is_error(result)) {
|
||
|
|
b_error_release(result);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
void b_object_to_string(struct _b_object *p, struct b_stream *out)
|
||
|
|
{
|
||
|
|
B_CLASS_DISPATCH_VIRTUAL_V(b_object, B_TYPE_OBJECT, p, to_string, p, out);
|
||
|
|
b_stream_write_fmt(out, NULL, "<%s@%p>", p->obj_type->r_info->t_name, p);
|
||
|
|
}
|
||
|
|
|
||
|
|
void *z__b_object_get_private(struct _b_object *object, b_type type)
|
||
|
|
{
|
||
|
|
if (b_type_id_compare(&object->obj_type->r_info->t_id, type) == 0) {
|
||
|
|
return (char *)object + object->obj_main_priv_offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct b_type_component *comp
|
||
|
|
= b_type_get_component(&object->obj_type->r_components, type);
|
||
|
|
if (!comp) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (char *)object + comp->c_instance_private_data_offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *z__b_object_get_protected(struct _b_object *object, b_type type)
|
||
|
|
{
|
||
|
|
struct b_type_component *comp
|
||
|
|
= b_type_get_component(&object->obj_type->r_components, type);
|
||
|
|
if (!comp) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (char *)object + comp->c_instance_protected_data_offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *z__b_object_get_interface(struct _b_object *object, b_type type)
|
||
|
|
{
|
||
|
|
return z__b_class_get_interface(object->obj_type->r_class, type);
|
||
|
|
}
|
||
|
|
|
||
|
|
struct _b_object *b_retain(struct _b_object *p)
|
||
|
|
{
|
||
|
|
p->obj_ref++;
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
void b_release(struct _b_object *p)
|
||
|
|
{
|
||
|
|
if (p->obj_ref > 1) {
|
||
|
|
p->obj_ref--;
|
||
|
|
}
|
||
|
|
|
||
|
|
p->obj_ref = 0;
|
||
|
|
const struct b_type_registration *type = p->obj_type;
|
||
|
|
|
||
|
|
struct b_queue_entry *cur = b_queue_last(&type->r_class_hierarchy);
|
||
|
|
while (cur) {
|
||
|
|
struct b_type_component *comp
|
||
|
|
= b_unbox(struct b_type_component, cur, c_entry);
|
||
|
|
|
||
|
|
const struct b_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 = b_queue_prev(cur);
|
||
|
|
}
|
||
|
|
|
||
|
|
p->obj_magic = 0;
|
||
|
|
p->obj_type = NULL;
|
||
|
|
|
||
|
|
free(p);
|
||
|
|
}
|