2025-08-16 16:03:55 +01:00
|
|
|
#include "object.h"
|
|
|
|
|
|
|
|
|
|
#include "type.h"
|
|
|
|
|
|
2025-10-15 10:38:18 +01:00
|
|
|
#include <blue/core/class.h>
|
|
|
|
|
#include <blue/core/macros.h>
|
|
|
|
|
#include <blue/core/object.h>
|
2025-08-16 16:03:55 +01:00
|
|
|
#include <blue/core/thread.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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 13:46:44 +01:00
|
|
|
void b_object_to_string(const struct _b_object *p, struct b_stream *out)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 13:46:44 +01:00
|
|
|
bool b_object_is_type(const struct _b_object *p, b_type type)
|
|
|
|
|
{
|
|
|
|
|
if (b_type_id_compare(&p->obj_type->r_info->t_id, type) == 0) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct b_type_component *comp
|
|
|
|
|
= b_type_get_component(&p->obj_type->r_components, type);
|
|
|
|
|
|
|
|
|
|
return comp != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 10:21:43 +01:00
|
|
|
void *b_object_get_private(const struct _b_object *object, b_type type)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 10:21:43 +01:00
|
|
|
void *b_object_get_protected(const struct _b_object *object, b_type type)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 10:21:43 +01:00
|
|
|
void *b_object_get_interface(const struct _b_object *object, b_type type)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
2025-10-19 10:21:43 +01:00
|
|
|
return b_class_get_interface(object->obj_type->r_class, type);
|
2025-08-16 16:03:55 +01:00
|
|
|
}
|
|
|
|
|
|
2025-10-18 21:51:51 +01:00
|
|
|
struct _b_object *b_object_ref(struct _b_object *p)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
|
|
|
|
p->obj_ref++;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-18 21:51:51 +01:00
|
|
|
void b_object_unref(struct _b_object *p)
|
2025-08-16 16:03:55 +01:00
|
|
|
{
|
|
|
|
|
if (p->obj_ref > 1) {
|
|
|
|
|
p->obj_ref--;
|
2025-10-18 21:51:51 +01:00
|
|
|
return;
|
2025-08-16 16:03:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2025-10-19 20:58:32 +01:00
|
|
|
|
|
|
|
|
struct _b_object *b_object_make_rvalue(struct _b_object *p)
|
|
|
|
|
{
|
|
|
|
|
p->obj_ref = 0;
|
|
|
|
|
return p;
|
|
|
|
|
}
|