size_t instance_size;
void (*class_init)(ObjectClass *klass, void *data);
+ void (*class_base_init)(ObjectClass *klass, void *data);
void (*class_finalize)(ObjectClass *klass, void *data);
void *class_data;
return g_hash_table_lookup(type_table_get(), name);
}
-TypeImpl *type_register(const TypeInfo *info)
+static TypeImpl *type_register_internal(const TypeInfo *info)
{
TypeImpl *ti = g_malloc0(sizeof(*ti));
ti->instance_size = info->instance_size;
ti->class_init = info->class_init;
+ ti->class_base_init = info->class_base_init;
ti->class_finalize = info->class_finalize;
ti->class_data = info->class_data;
return ti;
}
+TypeImpl *type_register(const TypeInfo *info)
+{
+ assert(info->parent);
+ return type_register_internal(info);
+}
+
TypeImpl *type_register_static(const TypeInfo *info)
{
return type_register(info);
char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
info.name = name;
- iface->type = type_register(&info);
+ iface->type = type_register_internal(&info);
g_free(name);
}
static void type_initialize(TypeImpl *ti)
{
- size_t class_size = sizeof(ObjectClass);
+ TypeImpl *parent;
int i;
if (ti->class) {
ti->instance_size = type_object_get_size(ti);
ti->class = g_malloc0(ti->class_size);
- ti->class->type = ti;
-
- if (type_has_parent(ti)) {
- TypeImpl *parent = type_get_parent(ti);
+ parent = type_get_parent(ti);
+ if (parent) {
type_initialize(parent);
- class_size = parent->class_size;
g_assert(parent->class_size <= ti->class_size);
-
- memcpy((void *)ti->class + sizeof(ObjectClass),
- (void *)parent->class + sizeof(ObjectClass),
- parent->class_size - sizeof(ObjectClass));
+ memcpy(ti->class, parent->class, parent->class_size);
}
- memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
+ ti->class->type = ti;
+
+ while (parent) {
+ if (parent->class_base_init) {
+ parent->class_base_init(ti->class, ti->class_data);
+ }
+ parent = type_get_parent(parent);
+ }
for (i = 0; i < ti->num_interfaces; i++) {
type_class_interface_init(ti, &ti->interfaces[i]);
object_initialize_with_type(data, type);
}
+static inline bool object_property_is_child(ObjectProperty *prop)
+{
+ return strstart(prop->type, "child<", NULL);
+}
+
+static inline bool object_property_is_link(ObjectProperty *prop)
+{
+ return strstart(prop->type, "link<", NULL);
+}
+
static void object_property_del_all(Object *obj)
{
while (!QTAILQ_EMPTY(&obj->properties)) {
ObjectProperty *prop;
QTAILQ_FOREACH(prop, &obj->properties, node) {
- if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
+ if (object_property_is_child(prop) && prop->opaque == child) {
object_property_del(obj, prop->name, errp);
break;
}
}
-static void register_types(void)
-{
- static TypeInfo interface_info = {
- .name = TYPE_INTERFACE,
- .instance_size = sizeof(Interface),
- .abstract = true,
- };
-
- type_interface = type_register_static(&interface_info);
-}
-
-type_init(register_types)
-
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
{
Object *inst;
return type->class;
}
+ObjectClass *object_class_get_parent(ObjectClass *class)
+{
+ TypeImpl *type = type_get_parent(class->type);
+
+ if (!type) {
+ return NULL;
+ }
+
+ type_initialize(type);
+
+ return type->class;
+}
+
typedef struct OCFData
{
void (*fn)(ObjectClass *klass, void *opaque);
g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
}
+int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
+ void *opaque)
+{
+ ObjectProperty *prop;
+ int ret = 0;
+
+ QTAILQ_FOREACH(prop, &obj->properties, node) {
+ if (object_property_is_child(prop)) {
+ ret = fn(prop->opaque, opaque);
+ if (ret != 0) {
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
{
GSList **list = opaque;
{
ObjectProperty *prop = object_property_find(obj, name);
- QTAILQ_REMOVE(&obj->properties, prop, node);
+ if (prop == NULL) {
+ error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
+ return;
+ }
- prop->release(obj, prop->name, prop->opaque);
+ if (prop->release) {
+ prop->release(obj, name, prop->opaque);
+ }
+
+ QTAILQ_REMOVE(&obj->properties, prop, node);
g_free(prop->name);
g_free(prop->type);
char *string;
mo = string_output_visitor_new();
- object_property_get(obj, string_output_get_visitor(mo), name, NULL);
+ object_property_get(obj, string_output_get_visitor(mo), name, errp);
string = string_output_get_string(mo);
string_output_visitor_cleanup(mo);
return string;
g_assert(obj->parent != NULL);
QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
return NULL;
}
- if (strstart(prop->type, "link<", NULL)) {
+ if (object_property_is_link(prop)) {
return *(Object **)prop->opaque;
- } else if (strstart(prop->type, "child<", NULL)) {
+ } else if (object_property_is_child(prop)) {
return prop->opaque;
} else {
return NULL;
QTAILQ_FOREACH(prop, &parent->properties, node) {
Object *found;
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
property_release_str,
prop, errp);
}
+
+static char *qdev_get_type(Object *obj, Error **errp)
+{
+ return g_strdup(object_get_typename(obj));
+}
+
+static void object_instance_init(Object *obj)
+{
+ object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
+}
+
+static void register_types(void)
+{
+ static TypeInfo interface_info = {
+ .name = TYPE_INTERFACE,
+ .instance_size = sizeof(Interface),
+ .abstract = true,
+ };
+
+ static TypeInfo object_info = {
+ .name = TYPE_OBJECT,
+ .instance_size = sizeof(Object),
+ .instance_init = object_instance_init,
+ .abstract = true,
+ };
+
+ type_interface = type_register_internal(&interface_info);
+ type_register_internal(&object_info);
+}
+
+type_init(register_types)