summaryrefslogtreecommitdiff
path: root/qom/object.c
diff options
context:
space:
mode:
Diffstat (limited to 'qom/object.c')
-rw-r--r--qom/object.c158
1 files changed, 113 insertions, 45 deletions
diff --git a/qom/object.c b/qom/object.c
index 6f839ad8c9..00bb3b029c 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -45,6 +45,7 @@ struct TypeImpl
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;
@@ -94,7 +95,7 @@ static TypeImpl *type_table_lookup(const char *name)
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));
@@ -112,6 +113,7 @@ TypeImpl *type_register(const TypeInfo *info)
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;
@@ -135,6 +137,12 @@ TypeImpl *type_register(const TypeInfo *info)
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);
@@ -202,13 +210,13 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
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) {
@@ -219,22 +227,23 @@ static void type_initialize(TypeImpl *ti)
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]);
@@ -296,6 +305,16 @@ void object_initialize(void *data, const char *typename)
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)) {
@@ -318,7 +337,7 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
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;
}
@@ -458,19 +477,6 @@ Object *object_dynamic_cast(Object *obj, const char *typename)
}
-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;
@@ -545,6 +551,19 @@ ObjectClass *object_class_by_name(const char *typename)
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);
@@ -584,6 +603,23 @@ void object_class_foreach(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;
@@ -636,7 +672,8 @@ void object_property_add(Object *obj, const char *name, const char *type,
QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
}
-static ObjectProperty *object_property_find(Object *obj, const char *name)
+ObjectProperty *object_property_find(Object *obj, const char *name,
+ Error **errp)
{
ObjectProperty *prop;
@@ -646,16 +683,22 @@ static ObjectProperty *object_property_find(Object *obj, const char *name)
}
}
+ error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return NULL;
}
void object_property_del(Object *obj, const char *name, Error **errp)
{
- ObjectProperty *prop = object_property_find(obj, name);
+ ObjectProperty *prop = object_property_find(obj, name, errp);
+ if (prop == NULL) {
+ return;
+ }
- QTAILQ_REMOVE(&obj->properties, prop, node);
+ if (prop->release) {
+ prop->release(obj, name, prop->opaque);
+ }
- prop->release(obj, prop->name, prop->opaque);
+ QTAILQ_REMOVE(&obj->properties, prop, node);
g_free(prop->name);
g_free(prop->type);
@@ -665,10 +708,8 @@ void object_property_del(Object *obj, const char *name, Error **errp)
void object_property_get(Object *obj, Visitor *v, const char *name,
Error **errp)
{
- ObjectProperty *prop = object_property_find(obj, name);
-
+ ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return;
}
@@ -682,10 +723,8 @@ void object_property_get(Object *obj, Visitor *v, const char *name,
void object_property_set(Object *obj, Visitor *v, const char *name,
Error **errp)
{
- ObjectProperty *prop = object_property_find(obj, name);
-
+ ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return;
}
@@ -838,10 +877,8 @@ char *object_property_print(Object *obj, const char *name,
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
{
- ObjectProperty *prop = object_property_find(obj, name);
-
+ ObjectProperty *prop = object_property_find(obj, name, errp);
if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
return NULL;
}
@@ -995,7 +1032,7 @@ gchar *object_get_canonical_path(Object *obj)
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;
}
@@ -1024,14 +1061,14 @@ gchar *object_get_canonical_path(Object *obj)
Object *object_resolve_path_component(Object *parent, gchar *part)
{
- ObjectProperty *prop = object_property_find(parent, part);
+ ObjectProperty *prop = object_property_find(parent, part, NULL);
if (prop == NULL) {
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;
@@ -1074,7 +1111,7 @@ static Object *object_resolve_partial_path(Object *parent,
QTAILQ_FOREACH(prop, &parent->properties, node) {
Object *found;
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
@@ -1194,3 +1231,34 @@ void object_property_add_str(Object *obj, const char *name,
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)