12f28d2ffSAnthony Liguori /* 22f28d2ffSAnthony Liguori * QEMU Object Model 32f28d2ffSAnthony Liguori * 42f28d2ffSAnthony Liguori * Copyright IBM, Corp. 2011 52f28d2ffSAnthony Liguori * 62f28d2ffSAnthony Liguori * Authors: 72f28d2ffSAnthony Liguori * Anthony Liguori <aliguori@us.ibm.com> 82f28d2ffSAnthony Liguori * 92f28d2ffSAnthony Liguori * This work is licensed under the terms of the GNU GPL, version 2 or later. 102f28d2ffSAnthony Liguori * See the COPYING file in the top-level directory. 112f28d2ffSAnthony Liguori */ 122f28d2ffSAnthony Liguori 1314cccb61SPaolo Bonzini #include "qom/object.h" 142f28d2ffSAnthony Liguori #include "qemu-common.h" 157b1b5d19SPaolo Bonzini #include "qapi/visitor.h" 16b2cd7deeSPaolo Bonzini #include "qapi/string-input-visitor.h" 17b2cd7deeSPaolo Bonzini #include "qapi/string-output-visitor.h" 187b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h" 192f28d2ffSAnthony Liguori 207b7b7d18SPaolo Bonzini /* TODO: replace QObject with a simpler visitor to avoid a dependency 217b7b7d18SPaolo Bonzini * of the QOM core on QObject? */ 2214cccb61SPaolo Bonzini #include "qom/qom-qobject.h" 237b1b5d19SPaolo Bonzini #include "qapi/qmp/qobject.h" 247b1b5d19SPaolo Bonzini #include "qapi/qmp/qbool.h" 257b1b5d19SPaolo Bonzini #include "qapi/qmp/qint.h" 267b1b5d19SPaolo Bonzini #include "qapi/qmp/qstring.h" 277b7b7d18SPaolo Bonzini 282f28d2ffSAnthony Liguori #define MAX_INTERFACES 32 292f28d2ffSAnthony Liguori 302f28d2ffSAnthony Liguori typedef struct InterfaceImpl InterfaceImpl; 312f28d2ffSAnthony Liguori typedef struct TypeImpl TypeImpl; 322f28d2ffSAnthony Liguori 332f28d2ffSAnthony Liguori struct InterfaceImpl 342f28d2ffSAnthony Liguori { 3533e95c63SAnthony Liguori const char *typename; 362f28d2ffSAnthony Liguori }; 372f28d2ffSAnthony Liguori 382f28d2ffSAnthony Liguori struct TypeImpl 392f28d2ffSAnthony Liguori { 402f28d2ffSAnthony Liguori const char *name; 412f28d2ffSAnthony Liguori 422f28d2ffSAnthony Liguori size_t class_size; 432f28d2ffSAnthony Liguori 442f28d2ffSAnthony Liguori size_t instance_size; 452f28d2ffSAnthony Liguori 462f28d2ffSAnthony Liguori void (*class_init)(ObjectClass *klass, void *data); 473b50e311SPaolo Bonzini void (*class_base_init)(ObjectClass *klass, void *data); 482f28d2ffSAnthony Liguori void (*class_finalize)(ObjectClass *klass, void *data); 492f28d2ffSAnthony Liguori 502f28d2ffSAnthony Liguori void *class_data; 512f28d2ffSAnthony Liguori 522f28d2ffSAnthony Liguori void (*instance_init)(Object *obj); 532f28d2ffSAnthony Liguori void (*instance_finalize)(Object *obj); 542f28d2ffSAnthony Liguori 552f28d2ffSAnthony Liguori bool abstract; 562f28d2ffSAnthony Liguori 572f28d2ffSAnthony Liguori const char *parent; 582f28d2ffSAnthony Liguori TypeImpl *parent_type; 592f28d2ffSAnthony Liguori 602f28d2ffSAnthony Liguori ObjectClass *class; 612f28d2ffSAnthony Liguori 622f28d2ffSAnthony Liguori int num_interfaces; 632f28d2ffSAnthony Liguori InterfaceImpl interfaces[MAX_INTERFACES]; 642f28d2ffSAnthony Liguori }; 652f28d2ffSAnthony Liguori 669970bd88SPaolo Bonzini static Type type_interface; 679970bd88SPaolo Bonzini 682f28d2ffSAnthony Liguori static GHashTable *type_table_get(void) 692f28d2ffSAnthony Liguori { 702f28d2ffSAnthony Liguori static GHashTable *type_table; 712f28d2ffSAnthony Liguori 722f28d2ffSAnthony Liguori if (type_table == NULL) { 732f28d2ffSAnthony Liguori type_table = g_hash_table_new(g_str_hash, g_str_equal); 742f28d2ffSAnthony Liguori } 752f28d2ffSAnthony Liguori 762f28d2ffSAnthony Liguori return type_table; 772f28d2ffSAnthony Liguori } 782f28d2ffSAnthony Liguori 792f28d2ffSAnthony Liguori static void type_table_add(TypeImpl *ti) 802f28d2ffSAnthony Liguori { 812f28d2ffSAnthony Liguori g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 822f28d2ffSAnthony Liguori } 832f28d2ffSAnthony Liguori 842f28d2ffSAnthony Liguori static TypeImpl *type_table_lookup(const char *name) 852f28d2ffSAnthony Liguori { 862f28d2ffSAnthony Liguori return g_hash_table_lookup(type_table_get(), name); 872f28d2ffSAnthony Liguori } 882f28d2ffSAnthony Liguori 89049cb3cfSPaolo Bonzini static TypeImpl *type_register_internal(const TypeInfo *info) 902f28d2ffSAnthony Liguori { 912f28d2ffSAnthony Liguori TypeImpl *ti = g_malloc0(sizeof(*ti)); 9233e95c63SAnthony Liguori int i; 932f28d2ffSAnthony Liguori 942f28d2ffSAnthony Liguori g_assert(info->name != NULL); 952f28d2ffSAnthony Liguori 9673093354SAnthony Liguori if (type_table_lookup(info->name) != NULL) { 9773093354SAnthony Liguori fprintf(stderr, "Registering `%s' which already exists\n", info->name); 9873093354SAnthony Liguori abort(); 9973093354SAnthony Liguori } 10073093354SAnthony Liguori 1012f28d2ffSAnthony Liguori ti->name = g_strdup(info->name); 1022f28d2ffSAnthony Liguori ti->parent = g_strdup(info->parent); 1032f28d2ffSAnthony Liguori 1042f28d2ffSAnthony Liguori ti->class_size = info->class_size; 1052f28d2ffSAnthony Liguori ti->instance_size = info->instance_size; 1062f28d2ffSAnthony Liguori 1072f28d2ffSAnthony Liguori ti->class_init = info->class_init; 1083b50e311SPaolo Bonzini ti->class_base_init = info->class_base_init; 1092f28d2ffSAnthony Liguori ti->class_finalize = info->class_finalize; 1102f28d2ffSAnthony Liguori ti->class_data = info->class_data; 1112f28d2ffSAnthony Liguori 1122f28d2ffSAnthony Liguori ti->instance_init = info->instance_init; 1132f28d2ffSAnthony Liguori ti->instance_finalize = info->instance_finalize; 1142f28d2ffSAnthony Liguori 1152f28d2ffSAnthony Liguori ti->abstract = info->abstract; 1162f28d2ffSAnthony Liguori 11733e95c63SAnthony Liguori for (i = 0; info->interfaces && info->interfaces[i].type; i++) { 11833e95c63SAnthony Liguori ti->interfaces[i].typename = g_strdup(info->interfaces[i].type); 1192f28d2ffSAnthony Liguori } 12033e95c63SAnthony Liguori ti->num_interfaces = i; 1212f28d2ffSAnthony Liguori 1222f28d2ffSAnthony Liguori type_table_add(ti); 1232f28d2ffSAnthony Liguori 1242f28d2ffSAnthony Liguori return ti; 1252f28d2ffSAnthony Liguori } 1262f28d2ffSAnthony Liguori 127049cb3cfSPaolo Bonzini TypeImpl *type_register(const TypeInfo *info) 128049cb3cfSPaolo Bonzini { 129049cb3cfSPaolo Bonzini assert(info->parent); 130049cb3cfSPaolo Bonzini return type_register_internal(info); 131049cb3cfSPaolo Bonzini } 132049cb3cfSPaolo Bonzini 1332f28d2ffSAnthony Liguori TypeImpl *type_register_static(const TypeInfo *info) 1342f28d2ffSAnthony Liguori { 1352f28d2ffSAnthony Liguori return type_register(info); 1362f28d2ffSAnthony Liguori } 1372f28d2ffSAnthony Liguori 1382f28d2ffSAnthony Liguori static TypeImpl *type_get_by_name(const char *name) 1392f28d2ffSAnthony Liguori { 1402f28d2ffSAnthony Liguori if (name == NULL) { 1412f28d2ffSAnthony Liguori return NULL; 1422f28d2ffSAnthony Liguori } 1432f28d2ffSAnthony Liguori 1442f28d2ffSAnthony Liguori return type_table_lookup(name); 1452f28d2ffSAnthony Liguori } 1462f28d2ffSAnthony Liguori 1472f28d2ffSAnthony Liguori static TypeImpl *type_get_parent(TypeImpl *type) 1482f28d2ffSAnthony Liguori { 1492f28d2ffSAnthony Liguori if (!type->parent_type && type->parent) { 1502f28d2ffSAnthony Liguori type->parent_type = type_get_by_name(type->parent); 1512f28d2ffSAnthony Liguori g_assert(type->parent_type != NULL); 1522f28d2ffSAnthony Liguori } 1532f28d2ffSAnthony Liguori 1542f28d2ffSAnthony Liguori return type->parent_type; 1552f28d2ffSAnthony Liguori } 1562f28d2ffSAnthony Liguori 1572f28d2ffSAnthony Liguori static bool type_has_parent(TypeImpl *type) 1582f28d2ffSAnthony Liguori { 1592f28d2ffSAnthony Liguori return (type->parent != NULL); 1602f28d2ffSAnthony Liguori } 1612f28d2ffSAnthony Liguori 1622f28d2ffSAnthony Liguori static size_t type_class_get_size(TypeImpl *ti) 1632f28d2ffSAnthony Liguori { 1642f28d2ffSAnthony Liguori if (ti->class_size) { 1652f28d2ffSAnthony Liguori return ti->class_size; 1662f28d2ffSAnthony Liguori } 1672f28d2ffSAnthony Liguori 1682f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 1692f28d2ffSAnthony Liguori return type_class_get_size(type_get_parent(ti)); 1702f28d2ffSAnthony Liguori } 1712f28d2ffSAnthony Liguori 1722f28d2ffSAnthony Liguori return sizeof(ObjectClass); 1732f28d2ffSAnthony Liguori } 1742f28d2ffSAnthony Liguori 175aca59af6SIgor Mitsyanko static size_t type_object_get_size(TypeImpl *ti) 176aca59af6SIgor Mitsyanko { 177aca59af6SIgor Mitsyanko if (ti->instance_size) { 178aca59af6SIgor Mitsyanko return ti->instance_size; 179aca59af6SIgor Mitsyanko } 180aca59af6SIgor Mitsyanko 181aca59af6SIgor Mitsyanko if (type_has_parent(ti)) { 182aca59af6SIgor Mitsyanko return type_object_get_size(type_get_parent(ti)); 183aca59af6SIgor Mitsyanko } 184aca59af6SIgor Mitsyanko 185aca59af6SIgor Mitsyanko return 0; 186aca59af6SIgor Mitsyanko } 187aca59af6SIgor Mitsyanko 18833e95c63SAnthony Liguori static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 1892f28d2ffSAnthony Liguori { 19033e95c63SAnthony Liguori assert(target_type); 1912f28d2ffSAnthony Liguori 19233e95c63SAnthony Liguori /* Check if typename is a direct ancestor of type */ 19333e95c63SAnthony Liguori while (type) { 19433e95c63SAnthony Liguori if (type == target_type) { 19533e95c63SAnthony Liguori return true; 19633e95c63SAnthony Liguori } 19733e95c63SAnthony Liguori 19833e95c63SAnthony Liguori type = type_get_parent(type); 19933e95c63SAnthony Liguori } 20033e95c63SAnthony Liguori 20133e95c63SAnthony Liguori return false; 20233e95c63SAnthony Liguori } 20333e95c63SAnthony Liguori 20433e95c63SAnthony Liguori static void type_initialize(TypeImpl *ti); 20533e95c63SAnthony Liguori 20633e95c63SAnthony Liguori static void type_initialize_interface(TypeImpl *ti, const char *parent) 20733e95c63SAnthony Liguori { 20833e95c63SAnthony Liguori InterfaceClass *new_iface; 20933e95c63SAnthony Liguori TypeInfo info = { }; 21033e95c63SAnthony Liguori TypeImpl *iface_impl; 21133e95c63SAnthony Liguori 21233e95c63SAnthony Liguori info.parent = parent; 21333e95c63SAnthony Liguori info.name = g_strdup_printf("%s::%s", ti->name, info.parent); 21433e95c63SAnthony Liguori info.abstract = true; 21533e95c63SAnthony Liguori 21633e95c63SAnthony Liguori iface_impl = type_register(&info); 21733e95c63SAnthony Liguori type_initialize(iface_impl); 21833e95c63SAnthony Liguori g_free((char *)info.name); 21933e95c63SAnthony Liguori 22033e95c63SAnthony Liguori new_iface = (InterfaceClass *)iface_impl->class; 22133e95c63SAnthony Liguori new_iface->concrete_class = ti->class; 22233e95c63SAnthony Liguori 22333e95c63SAnthony Liguori ti->class->interfaces = g_slist_append(ti->class->interfaces, 22433e95c63SAnthony Liguori iface_impl->class); 2252f28d2ffSAnthony Liguori } 2262f28d2ffSAnthony Liguori 227ac451033SIgor Mitsyanko static void type_initialize(TypeImpl *ti) 2282f28d2ffSAnthony Liguori { 229745549c8SPaolo Bonzini TypeImpl *parent; 2302f28d2ffSAnthony Liguori 2312f28d2ffSAnthony Liguori if (ti->class) { 2322f28d2ffSAnthony Liguori return; 2332f28d2ffSAnthony Liguori } 2342f28d2ffSAnthony Liguori 2352f28d2ffSAnthony Liguori ti->class_size = type_class_get_size(ti); 236aca59af6SIgor Mitsyanko ti->instance_size = type_object_get_size(ti); 2372f28d2ffSAnthony Liguori 2382f28d2ffSAnthony Liguori ti->class = g_malloc0(ti->class_size); 2392f28d2ffSAnthony Liguori 240745549c8SPaolo Bonzini parent = type_get_parent(ti); 241745549c8SPaolo Bonzini if (parent) { 242ac451033SIgor Mitsyanko type_initialize(parent); 24333e95c63SAnthony Liguori GSList *e; 24433e95c63SAnthony Liguori int i; 2452f28d2ffSAnthony Liguori 2462f28d2ffSAnthony Liguori g_assert(parent->class_size <= ti->class_size); 247745549c8SPaolo Bonzini memcpy(ti->class, parent->class, parent->class_size); 24833e95c63SAnthony Liguori 24933e95c63SAnthony Liguori for (e = parent->class->interfaces; e; e = e->next) { 25033e95c63SAnthony Liguori ObjectClass *iface = e->data; 25133e95c63SAnthony Liguori type_initialize_interface(ti, object_class_get_name(iface)); 25233e95c63SAnthony Liguori } 25333e95c63SAnthony Liguori 25433e95c63SAnthony Liguori for (i = 0; i < ti->num_interfaces; i++) { 25533e95c63SAnthony Liguori TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); 25633e95c63SAnthony Liguori for (e = ti->class->interfaces; e; e = e->next) { 25733e95c63SAnthony Liguori TypeImpl *target_type = OBJECT_CLASS(e->data)->type; 25833e95c63SAnthony Liguori 25933e95c63SAnthony Liguori if (type_is_ancestor(target_type, t)) { 26033e95c63SAnthony Liguori break; 26133e95c63SAnthony Liguori } 26233e95c63SAnthony Liguori } 26333e95c63SAnthony Liguori 26433e95c63SAnthony Liguori if (e) { 26533e95c63SAnthony Liguori continue; 26633e95c63SAnthony Liguori } 26733e95c63SAnthony Liguori 26833e95c63SAnthony Liguori type_initialize_interface(ti, ti->interfaces[i].typename); 26933e95c63SAnthony Liguori } 270745549c8SPaolo Bonzini } 2712f28d2ffSAnthony Liguori 272745549c8SPaolo Bonzini ti->class->type = ti; 2733b50e311SPaolo Bonzini 2743b50e311SPaolo Bonzini while (parent) { 2753b50e311SPaolo Bonzini if (parent->class_base_init) { 2763b50e311SPaolo Bonzini parent->class_base_init(ti->class, ti->class_data); 2773b50e311SPaolo Bonzini } 2783b50e311SPaolo Bonzini parent = type_get_parent(parent); 2793b50e311SPaolo Bonzini } 2802f28d2ffSAnthony Liguori 2812f28d2ffSAnthony Liguori if (ti->class_init) { 2822f28d2ffSAnthony Liguori ti->class_init(ti->class, ti->class_data); 2832f28d2ffSAnthony Liguori } 2842f28d2ffSAnthony Liguori 2852f28d2ffSAnthony Liguori 2862f28d2ffSAnthony Liguori } 2872f28d2ffSAnthony Liguori 2882f28d2ffSAnthony Liguori static void object_init_with_type(Object *obj, TypeImpl *ti) 2892f28d2ffSAnthony Liguori { 2902f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 2912f28d2ffSAnthony Liguori object_init_with_type(obj, type_get_parent(ti)); 2922f28d2ffSAnthony Liguori } 2932f28d2ffSAnthony Liguori 2942f28d2ffSAnthony Liguori if (ti->instance_init) { 2952f28d2ffSAnthony Liguori ti->instance_init(obj); 2962f28d2ffSAnthony Liguori } 2972f28d2ffSAnthony Liguori } 2982f28d2ffSAnthony Liguori 2992f28d2ffSAnthony Liguori void object_initialize_with_type(void *data, TypeImpl *type) 3002f28d2ffSAnthony Liguori { 3012f28d2ffSAnthony Liguori Object *obj = data; 3022f28d2ffSAnthony Liguori 3032f28d2ffSAnthony Liguori g_assert(type != NULL); 304ac451033SIgor Mitsyanko type_initialize(type); 305aca59af6SIgor Mitsyanko 306aca59af6SIgor Mitsyanko g_assert(type->instance_size >= sizeof(Object)); 3072f28d2ffSAnthony Liguori g_assert(type->abstract == false); 3082f28d2ffSAnthony Liguori 3092f28d2ffSAnthony Liguori memset(obj, 0, type->instance_size); 3102f28d2ffSAnthony Liguori obj->class = type->class; 311764b6312SPaolo Bonzini object_ref(obj); 31257c9fafeSAnthony Liguori QTAILQ_INIT(&obj->properties); 3132f28d2ffSAnthony Liguori object_init_with_type(obj, type); 3142f28d2ffSAnthony Liguori } 3152f28d2ffSAnthony Liguori 3162f28d2ffSAnthony Liguori void object_initialize(void *data, const char *typename) 3172f28d2ffSAnthony Liguori { 3182f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 3192f28d2ffSAnthony Liguori 3202f28d2ffSAnthony Liguori object_initialize_with_type(data, type); 3212f28d2ffSAnthony Liguori } 3222f28d2ffSAnthony Liguori 3235d9d3f47SAndreas Färber static inline bool object_property_is_child(ObjectProperty *prop) 3245d9d3f47SAndreas Färber { 3255d9d3f47SAndreas Färber return strstart(prop->type, "child<", NULL); 3265d9d3f47SAndreas Färber } 3275d9d3f47SAndreas Färber 3285d9d3f47SAndreas Färber static inline bool object_property_is_link(ObjectProperty *prop) 3295d9d3f47SAndreas Färber { 3305d9d3f47SAndreas Färber return strstart(prop->type, "link<", NULL); 3315d9d3f47SAndreas Färber } 3325d9d3f47SAndreas Färber 33357c9fafeSAnthony Liguori static void object_property_del_all(Object *obj) 33457c9fafeSAnthony Liguori { 33557c9fafeSAnthony Liguori while (!QTAILQ_EMPTY(&obj->properties)) { 33657c9fafeSAnthony Liguori ObjectProperty *prop = QTAILQ_FIRST(&obj->properties); 33757c9fafeSAnthony Liguori 33857c9fafeSAnthony Liguori QTAILQ_REMOVE(&obj->properties, prop, node); 33957c9fafeSAnthony Liguori 34057c9fafeSAnthony Liguori if (prop->release) { 34157c9fafeSAnthony Liguori prop->release(obj, prop->name, prop->opaque); 34257c9fafeSAnthony Liguori } 34357c9fafeSAnthony Liguori 34457c9fafeSAnthony Liguori g_free(prop->name); 34557c9fafeSAnthony Liguori g_free(prop->type); 34657c9fafeSAnthony Liguori g_free(prop); 34757c9fafeSAnthony Liguori } 34857c9fafeSAnthony Liguori } 34957c9fafeSAnthony Liguori 35057c9fafeSAnthony Liguori static void object_property_del_child(Object *obj, Object *child, Error **errp) 35157c9fafeSAnthony Liguori { 35257c9fafeSAnthony Liguori ObjectProperty *prop; 35357c9fafeSAnthony Liguori 35457c9fafeSAnthony Liguori QTAILQ_FOREACH(prop, &obj->properties, node) { 3555d9d3f47SAndreas Färber if (object_property_is_child(prop) && prop->opaque == child) { 35657c9fafeSAnthony Liguori object_property_del(obj, prop->name, errp); 3576c1fdcf9SPaolo Bonzini break; 35857c9fafeSAnthony Liguori } 35957c9fafeSAnthony Liguori } 36057c9fafeSAnthony Liguori } 36157c9fafeSAnthony Liguori 36257c9fafeSAnthony Liguori void object_unparent(Object *obj) 36357c9fafeSAnthony Liguori { 36457c9fafeSAnthony Liguori if (obj->parent) { 36557c9fafeSAnthony Liguori object_property_del_child(obj->parent, obj, NULL); 36657c9fafeSAnthony Liguori } 367667d22d1SPaolo Bonzini if (obj->class->unparent) { 368667d22d1SPaolo Bonzini (obj->class->unparent)(obj); 369667d22d1SPaolo Bonzini } 37057c9fafeSAnthony Liguori } 37157c9fafeSAnthony Liguori 3722f28d2ffSAnthony Liguori static void object_deinit(Object *obj, TypeImpl *type) 3732f28d2ffSAnthony Liguori { 3742f28d2ffSAnthony Liguori if (type->instance_finalize) { 3752f28d2ffSAnthony Liguori type->instance_finalize(obj); 3762f28d2ffSAnthony Liguori } 3772f28d2ffSAnthony Liguori 3782f28d2ffSAnthony Liguori if (type_has_parent(type)) { 3792f28d2ffSAnthony Liguori object_deinit(obj, type_get_parent(type)); 3802f28d2ffSAnthony Liguori } 3812f28d2ffSAnthony Liguori } 3822f28d2ffSAnthony Liguori 383339c2708SPaolo Bonzini static void object_finalize(void *data) 3842f28d2ffSAnthony Liguori { 3852f28d2ffSAnthony Liguori Object *obj = data; 3862f28d2ffSAnthony Liguori TypeImpl *ti = obj->class->type; 3872f28d2ffSAnthony Liguori 3882f28d2ffSAnthony Liguori object_deinit(obj, ti); 38957c9fafeSAnthony Liguori object_property_del_all(obj); 390db85b575SAnthony Liguori 391db85b575SAnthony Liguori g_assert(obj->ref == 0); 392fde9bf44SPaolo Bonzini if (obj->free) { 393fde9bf44SPaolo Bonzini obj->free(obj); 394fde9bf44SPaolo Bonzini } 3952f28d2ffSAnthony Liguori } 3962f28d2ffSAnthony Liguori 3972f28d2ffSAnthony Liguori Object *object_new_with_type(Type type) 3982f28d2ffSAnthony Liguori { 3992f28d2ffSAnthony Liguori Object *obj; 4002f28d2ffSAnthony Liguori 4012f28d2ffSAnthony Liguori g_assert(type != NULL); 402ac451033SIgor Mitsyanko type_initialize(type); 4032f28d2ffSAnthony Liguori 4042f28d2ffSAnthony Liguori obj = g_malloc(type->instance_size); 4052f28d2ffSAnthony Liguori object_initialize_with_type(obj, type); 406fde9bf44SPaolo Bonzini obj->free = g_free; 4072f28d2ffSAnthony Liguori 4082f28d2ffSAnthony Liguori return obj; 4092f28d2ffSAnthony Liguori } 4102f28d2ffSAnthony Liguori 4112f28d2ffSAnthony Liguori Object *object_new(const char *typename) 4122f28d2ffSAnthony Liguori { 4132f28d2ffSAnthony Liguori TypeImpl *ti = type_get_by_name(typename); 4142f28d2ffSAnthony Liguori 4152f28d2ffSAnthony Liguori return object_new_with_type(ti); 4162f28d2ffSAnthony Liguori } 4172f28d2ffSAnthony Liguori 4182f28d2ffSAnthony Liguori void object_delete(Object *obj) 4192f28d2ffSAnthony Liguori { 420da5a44e8SPaolo Bonzini object_unparent(obj); 421da5a44e8SPaolo Bonzini g_assert(obj->ref == 1); 422db85b575SAnthony Liguori object_unref(obj); 4232f28d2ffSAnthony Liguori } 4242f28d2ffSAnthony Liguori 4252f28d2ffSAnthony Liguori Object *object_dynamic_cast(Object *obj, const char *typename) 4262f28d2ffSAnthony Liguori { 427b7f43fe4SPaolo Bonzini if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) { 428acc4af3fSPaolo Bonzini return obj; 429acc4af3fSPaolo Bonzini } 430acc4af3fSPaolo Bonzini 4312f28d2ffSAnthony Liguori return NULL; 4322f28d2ffSAnthony Liguori } 4332f28d2ffSAnthony Liguori 4342f28d2ffSAnthony Liguori Object *object_dynamic_cast_assert(Object *obj, const char *typename) 4352f28d2ffSAnthony Liguori { 4362f28d2ffSAnthony Liguori Object *inst; 4372f28d2ffSAnthony Liguori 4382f28d2ffSAnthony Liguori inst = object_dynamic_cast(obj, typename); 4392f28d2ffSAnthony Liguori 440b7f43fe4SPaolo Bonzini if (!inst && obj) { 4412f28d2ffSAnthony Liguori fprintf(stderr, "Object %p is not an instance of type %s\n", 4422f28d2ffSAnthony Liguori obj, typename); 4432f28d2ffSAnthony Liguori abort(); 4442f28d2ffSAnthony Liguori } 4452f28d2ffSAnthony Liguori 4462f28d2ffSAnthony Liguori return inst; 4472f28d2ffSAnthony Liguori } 4482f28d2ffSAnthony Liguori 4492f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast(ObjectClass *class, 4502f28d2ffSAnthony Liguori const char *typename) 4512f28d2ffSAnthony Liguori { 4522f28d2ffSAnthony Liguori TypeImpl *target_type = type_get_by_name(typename); 4532f28d2ffSAnthony Liguori TypeImpl *type = class->type; 45433e95c63SAnthony Liguori ObjectClass *ret = NULL; 4552f28d2ffSAnthony Liguori 45633e95c63SAnthony Liguori if (type->num_interfaces && type_is_ancestor(target_type, type_interface)) { 45733e95c63SAnthony Liguori int found = 0; 45833e95c63SAnthony Liguori GSList *i; 45933e95c63SAnthony Liguori 46033e95c63SAnthony Liguori for (i = class->interfaces; i; i = i->next) { 46133e95c63SAnthony Liguori ObjectClass *target_class = i->data; 46233e95c63SAnthony Liguori 46333e95c63SAnthony Liguori if (type_is_ancestor(target_class->type, target_type)) { 46433e95c63SAnthony Liguori ret = target_class; 46533e95c63SAnthony Liguori found++; 46633e95c63SAnthony Liguori } 4672f28d2ffSAnthony Liguori } 4682f28d2ffSAnthony Liguori 46933e95c63SAnthony Liguori /* The match was ambiguous, don't allow a cast */ 47033e95c63SAnthony Liguori if (found > 1) { 47133e95c63SAnthony Liguori ret = NULL; 47233e95c63SAnthony Liguori } 47333e95c63SAnthony Liguori } else if (type_is_ancestor(type, target_type)) { 47433e95c63SAnthony Liguori ret = class; 4752f28d2ffSAnthony Liguori } 4762f28d2ffSAnthony Liguori 47733e95c63SAnthony Liguori return ret; 4782f28d2ffSAnthony Liguori } 4792f28d2ffSAnthony Liguori 4802f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 4812f28d2ffSAnthony Liguori const char *typename) 4822f28d2ffSAnthony Liguori { 4832f28d2ffSAnthony Liguori ObjectClass *ret = object_class_dynamic_cast(class, typename); 4842f28d2ffSAnthony Liguori 4852f28d2ffSAnthony Liguori if (!ret) { 4862f28d2ffSAnthony Liguori fprintf(stderr, "Object %p is not an instance of type %s\n", 4872f28d2ffSAnthony Liguori class, typename); 4882f28d2ffSAnthony Liguori abort(); 4892f28d2ffSAnthony Liguori } 4902f28d2ffSAnthony Liguori 4912f28d2ffSAnthony Liguori return ret; 4922f28d2ffSAnthony Liguori } 4932f28d2ffSAnthony Liguori 4942f28d2ffSAnthony Liguori const char *object_get_typename(Object *obj) 4952f28d2ffSAnthony Liguori { 4962f28d2ffSAnthony Liguori return obj->class->type->name; 4972f28d2ffSAnthony Liguori } 4982f28d2ffSAnthony Liguori 4992f28d2ffSAnthony Liguori ObjectClass *object_get_class(Object *obj) 5002f28d2ffSAnthony Liguori { 5012f28d2ffSAnthony Liguori return obj->class; 5022f28d2ffSAnthony Liguori } 5032f28d2ffSAnthony Liguori 5042f28d2ffSAnthony Liguori const char *object_class_get_name(ObjectClass *klass) 5052f28d2ffSAnthony Liguori { 5062f28d2ffSAnthony Liguori return klass->type->name; 5072f28d2ffSAnthony Liguori } 5082f28d2ffSAnthony Liguori 5092f28d2ffSAnthony Liguori ObjectClass *object_class_by_name(const char *typename) 5102f28d2ffSAnthony Liguori { 5112f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 5122f28d2ffSAnthony Liguori 5132f28d2ffSAnthony Liguori if (!type) { 5142f28d2ffSAnthony Liguori return NULL; 5152f28d2ffSAnthony Liguori } 5162f28d2ffSAnthony Liguori 517ac451033SIgor Mitsyanko type_initialize(type); 5182f28d2ffSAnthony Liguori 5192f28d2ffSAnthony Liguori return type->class; 5202f28d2ffSAnthony Liguori } 5212f28d2ffSAnthony Liguori 522e7cce67fSPaolo Bonzini ObjectClass *object_class_get_parent(ObjectClass *class) 523e7cce67fSPaolo Bonzini { 524e7cce67fSPaolo Bonzini TypeImpl *type = type_get_parent(class->type); 525e7cce67fSPaolo Bonzini 526e7cce67fSPaolo Bonzini if (!type) { 527e7cce67fSPaolo Bonzini return NULL; 528e7cce67fSPaolo Bonzini } 529e7cce67fSPaolo Bonzini 530e7cce67fSPaolo Bonzini type_initialize(type); 531e7cce67fSPaolo Bonzini 532e7cce67fSPaolo Bonzini return type->class; 533e7cce67fSPaolo Bonzini } 534e7cce67fSPaolo Bonzini 5352f28d2ffSAnthony Liguori typedef struct OCFData 5362f28d2ffSAnthony Liguori { 5372f28d2ffSAnthony Liguori void (*fn)(ObjectClass *klass, void *opaque); 53893c511a1SAnthony Liguori const char *implements_type; 53993c511a1SAnthony Liguori bool include_abstract; 5402f28d2ffSAnthony Liguori void *opaque; 5412f28d2ffSAnthony Liguori } OCFData; 5422f28d2ffSAnthony Liguori 5432f28d2ffSAnthony Liguori static void object_class_foreach_tramp(gpointer key, gpointer value, 5442f28d2ffSAnthony Liguori gpointer opaque) 5452f28d2ffSAnthony Liguori { 5462f28d2ffSAnthony Liguori OCFData *data = opaque; 5472f28d2ffSAnthony Liguori TypeImpl *type = value; 54893c511a1SAnthony Liguori ObjectClass *k; 5492f28d2ffSAnthony Liguori 550ac451033SIgor Mitsyanko type_initialize(type); 55193c511a1SAnthony Liguori k = type->class; 5522f28d2ffSAnthony Liguori 55393c511a1SAnthony Liguori if (!data->include_abstract && type->abstract) { 55493c511a1SAnthony Liguori return; 55593c511a1SAnthony Liguori } 55693c511a1SAnthony Liguori 55793c511a1SAnthony Liguori if (data->implements_type && 55893c511a1SAnthony Liguori !object_class_dynamic_cast(k, data->implements_type)) { 55993c511a1SAnthony Liguori return; 56093c511a1SAnthony Liguori } 56193c511a1SAnthony Liguori 56293c511a1SAnthony Liguori data->fn(k, data->opaque); 5632f28d2ffSAnthony Liguori } 5642f28d2ffSAnthony Liguori 5652f28d2ffSAnthony Liguori void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 56693c511a1SAnthony Liguori const char *implements_type, bool include_abstract, 5672f28d2ffSAnthony Liguori void *opaque) 5682f28d2ffSAnthony Liguori { 56993c511a1SAnthony Liguori OCFData data = { fn, implements_type, include_abstract, opaque }; 5702f28d2ffSAnthony Liguori 5712f28d2ffSAnthony Liguori g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 5722f28d2ffSAnthony Liguori } 57357c9fafeSAnthony Liguori 57432efc535SPaolo Bonzini int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), 57532efc535SPaolo Bonzini void *opaque) 57632efc535SPaolo Bonzini { 57732efc535SPaolo Bonzini ObjectProperty *prop; 57832efc535SPaolo Bonzini int ret = 0; 57932efc535SPaolo Bonzini 58032efc535SPaolo Bonzini QTAILQ_FOREACH(prop, &obj->properties, node) { 58132efc535SPaolo Bonzini if (object_property_is_child(prop)) { 58232efc535SPaolo Bonzini ret = fn(prop->opaque, opaque); 58332efc535SPaolo Bonzini if (ret != 0) { 58432efc535SPaolo Bonzini break; 58532efc535SPaolo Bonzini } 58632efc535SPaolo Bonzini } 58732efc535SPaolo Bonzini } 58832efc535SPaolo Bonzini return ret; 58932efc535SPaolo Bonzini } 59032efc535SPaolo Bonzini 591418ba9e5SAndreas Färber static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) 592418ba9e5SAndreas Färber { 593418ba9e5SAndreas Färber GSList **list = opaque; 594418ba9e5SAndreas Färber 595418ba9e5SAndreas Färber *list = g_slist_prepend(*list, klass); 596418ba9e5SAndreas Färber } 597418ba9e5SAndreas Färber 598418ba9e5SAndreas Färber GSList *object_class_get_list(const char *implements_type, 599418ba9e5SAndreas Färber bool include_abstract) 600418ba9e5SAndreas Färber { 601418ba9e5SAndreas Färber GSList *list = NULL; 602418ba9e5SAndreas Färber 603418ba9e5SAndreas Färber object_class_foreach(object_class_get_list_tramp, 604418ba9e5SAndreas Färber implements_type, include_abstract, &list); 605418ba9e5SAndreas Färber return list; 606418ba9e5SAndreas Färber } 607418ba9e5SAndreas Färber 60857c9fafeSAnthony Liguori void object_ref(Object *obj) 60957c9fafeSAnthony Liguori { 61057c9fafeSAnthony Liguori obj->ref++; 61157c9fafeSAnthony Liguori } 61257c9fafeSAnthony Liguori 61357c9fafeSAnthony Liguori void object_unref(Object *obj) 61457c9fafeSAnthony Liguori { 61557c9fafeSAnthony Liguori g_assert(obj->ref > 0); 61657c9fafeSAnthony Liguori obj->ref--; 61757c9fafeSAnthony Liguori 61857c9fafeSAnthony Liguori /* parent always holds a reference to its children */ 61957c9fafeSAnthony Liguori if (obj->ref == 0) { 62057c9fafeSAnthony Liguori object_finalize(obj); 62157c9fafeSAnthony Liguori } 62257c9fafeSAnthony Liguori } 62357c9fafeSAnthony Liguori 62457c9fafeSAnthony Liguori void object_property_add(Object *obj, const char *name, const char *type, 62557c9fafeSAnthony Liguori ObjectPropertyAccessor *get, 62657c9fafeSAnthony Liguori ObjectPropertyAccessor *set, 62757c9fafeSAnthony Liguori ObjectPropertyRelease *release, 62857c9fafeSAnthony Liguori void *opaque, Error **errp) 62957c9fafeSAnthony Liguori { 63057c9fafeSAnthony Liguori ObjectProperty *prop = g_malloc0(sizeof(*prop)); 63157c9fafeSAnthony Liguori 63257c9fafeSAnthony Liguori prop->name = g_strdup(name); 63357c9fafeSAnthony Liguori prop->type = g_strdup(type); 63457c9fafeSAnthony Liguori 63557c9fafeSAnthony Liguori prop->get = get; 63657c9fafeSAnthony Liguori prop->set = set; 63757c9fafeSAnthony Liguori prop->release = release; 63857c9fafeSAnthony Liguori prop->opaque = opaque; 63957c9fafeSAnthony Liguori 64057c9fafeSAnthony Liguori QTAILQ_INSERT_TAIL(&obj->properties, prop, node); 64157c9fafeSAnthony Liguori } 64257c9fafeSAnthony Liguori 64389bfe000SPaolo Bonzini ObjectProperty *object_property_find(Object *obj, const char *name, 64489bfe000SPaolo Bonzini Error **errp) 64557c9fafeSAnthony Liguori { 64657c9fafeSAnthony Liguori ObjectProperty *prop; 64757c9fafeSAnthony Liguori 64857c9fafeSAnthony Liguori QTAILQ_FOREACH(prop, &obj->properties, node) { 64957c9fafeSAnthony Liguori if (strcmp(prop->name, name) == 0) { 65057c9fafeSAnthony Liguori return prop; 65157c9fafeSAnthony Liguori } 65257c9fafeSAnthony Liguori } 65357c9fafeSAnthony Liguori 65489bfe000SPaolo Bonzini error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); 65557c9fafeSAnthony Liguori return NULL; 65657c9fafeSAnthony Liguori } 65757c9fafeSAnthony Liguori 65857c9fafeSAnthony Liguori void object_property_del(Object *obj, const char *name, Error **errp) 65957c9fafeSAnthony Liguori { 66089bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 6610866aca1SAnthony Liguori if (prop == NULL) { 6620866aca1SAnthony Liguori return; 6630866aca1SAnthony Liguori } 66457c9fafeSAnthony Liguori 6650866aca1SAnthony Liguori if (prop->release) { 6660866aca1SAnthony Liguori prop->release(obj, name, prop->opaque); 6670866aca1SAnthony Liguori } 6680866aca1SAnthony Liguori 6690866aca1SAnthony Liguori QTAILQ_REMOVE(&obj->properties, prop, node); 67057c9fafeSAnthony Liguori 67157c9fafeSAnthony Liguori g_free(prop->name); 67257c9fafeSAnthony Liguori g_free(prop->type); 67357c9fafeSAnthony Liguori g_free(prop); 67457c9fafeSAnthony Liguori } 67557c9fafeSAnthony Liguori 67657c9fafeSAnthony Liguori void object_property_get(Object *obj, Visitor *v, const char *name, 67757c9fafeSAnthony Liguori Error **errp) 67857c9fafeSAnthony Liguori { 67989bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 68057c9fafeSAnthony Liguori if (prop == NULL) { 68157c9fafeSAnthony Liguori return; 68257c9fafeSAnthony Liguori } 68357c9fafeSAnthony Liguori 68457c9fafeSAnthony Liguori if (!prop->get) { 68557c9fafeSAnthony Liguori error_set(errp, QERR_PERMISSION_DENIED); 68657c9fafeSAnthony Liguori } else { 68757c9fafeSAnthony Liguori prop->get(obj, v, prop->opaque, name, errp); 68857c9fafeSAnthony Liguori } 68957c9fafeSAnthony Liguori } 69057c9fafeSAnthony Liguori 69157c9fafeSAnthony Liguori void object_property_set(Object *obj, Visitor *v, const char *name, 69257c9fafeSAnthony Liguori Error **errp) 69357c9fafeSAnthony Liguori { 69489bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 69557c9fafeSAnthony Liguori if (prop == NULL) { 69657c9fafeSAnthony Liguori return; 69757c9fafeSAnthony Liguori } 69857c9fafeSAnthony Liguori 69957c9fafeSAnthony Liguori if (!prop->set) { 70057c9fafeSAnthony Liguori error_set(errp, QERR_PERMISSION_DENIED); 70157c9fafeSAnthony Liguori } else { 70257c9fafeSAnthony Liguori prop->set(obj, v, prop->opaque, name, errp); 70357c9fafeSAnthony Liguori } 70457c9fafeSAnthony Liguori } 70557c9fafeSAnthony Liguori 7067b7b7d18SPaolo Bonzini void object_property_set_str(Object *obj, const char *value, 7077b7b7d18SPaolo Bonzini const char *name, Error **errp) 7087b7b7d18SPaolo Bonzini { 7097b7b7d18SPaolo Bonzini QString *qstr = qstring_from_str(value); 7107b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qstr), name, errp); 7117b7b7d18SPaolo Bonzini 7127b7b7d18SPaolo Bonzini QDECREF(qstr); 7137b7b7d18SPaolo Bonzini } 7147b7b7d18SPaolo Bonzini 7157b7b7d18SPaolo Bonzini char *object_property_get_str(Object *obj, const char *name, 7167b7b7d18SPaolo Bonzini Error **errp) 7177b7b7d18SPaolo Bonzini { 7187b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 7197b7b7d18SPaolo Bonzini QString *qstring; 7207b7b7d18SPaolo Bonzini char *retval; 7217b7b7d18SPaolo Bonzini 7227b7b7d18SPaolo Bonzini if (!ret) { 7237b7b7d18SPaolo Bonzini return NULL; 7247b7b7d18SPaolo Bonzini } 7257b7b7d18SPaolo Bonzini qstring = qobject_to_qstring(ret); 7267b7b7d18SPaolo Bonzini if (!qstring) { 7277b7b7d18SPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); 7287b7b7d18SPaolo Bonzini retval = NULL; 7297b7b7d18SPaolo Bonzini } else { 7307b7b7d18SPaolo Bonzini retval = g_strdup(qstring_get_str(qstring)); 7317b7b7d18SPaolo Bonzini } 7327b7b7d18SPaolo Bonzini 7337b7b7d18SPaolo Bonzini QDECREF(qstring); 7347b7b7d18SPaolo Bonzini return retval; 7357b7b7d18SPaolo Bonzini } 7367b7b7d18SPaolo Bonzini 7371d9c5a12SPaolo Bonzini void object_property_set_link(Object *obj, Object *value, 7381d9c5a12SPaolo Bonzini const char *name, Error **errp) 7391d9c5a12SPaolo Bonzini { 7401d9c5a12SPaolo Bonzini object_property_set_str(obj, object_get_canonical_path(value), 7411d9c5a12SPaolo Bonzini name, errp); 7421d9c5a12SPaolo Bonzini } 7431d9c5a12SPaolo Bonzini 7441d9c5a12SPaolo Bonzini Object *object_property_get_link(Object *obj, const char *name, 7451d9c5a12SPaolo Bonzini Error **errp) 7461d9c5a12SPaolo Bonzini { 7471d9c5a12SPaolo Bonzini char *str = object_property_get_str(obj, name, errp); 7481d9c5a12SPaolo Bonzini Object *target = NULL; 7491d9c5a12SPaolo Bonzini 7501d9c5a12SPaolo Bonzini if (str && *str) { 7511d9c5a12SPaolo Bonzini target = object_resolve_path(str, NULL); 7521d9c5a12SPaolo Bonzini if (!target) { 7531d9c5a12SPaolo Bonzini error_set(errp, QERR_DEVICE_NOT_FOUND, str); 7541d9c5a12SPaolo Bonzini } 7551d9c5a12SPaolo Bonzini } 7561d9c5a12SPaolo Bonzini 7571d9c5a12SPaolo Bonzini g_free(str); 7581d9c5a12SPaolo Bonzini return target; 7591d9c5a12SPaolo Bonzini } 7601d9c5a12SPaolo Bonzini 7617b7b7d18SPaolo Bonzini void object_property_set_bool(Object *obj, bool value, 7627b7b7d18SPaolo Bonzini const char *name, Error **errp) 7637b7b7d18SPaolo Bonzini { 7647b7b7d18SPaolo Bonzini QBool *qbool = qbool_from_int(value); 7657b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qbool), name, errp); 7667b7b7d18SPaolo Bonzini 7677b7b7d18SPaolo Bonzini QDECREF(qbool); 7687b7b7d18SPaolo Bonzini } 7697b7b7d18SPaolo Bonzini 7707b7b7d18SPaolo Bonzini bool object_property_get_bool(Object *obj, const char *name, 7717b7b7d18SPaolo Bonzini Error **errp) 7727b7b7d18SPaolo Bonzini { 7737b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 7747b7b7d18SPaolo Bonzini QBool *qbool; 7757b7b7d18SPaolo Bonzini bool retval; 7767b7b7d18SPaolo Bonzini 7777b7b7d18SPaolo Bonzini if (!ret) { 7787b7b7d18SPaolo Bonzini return false; 7797b7b7d18SPaolo Bonzini } 7807b7b7d18SPaolo Bonzini qbool = qobject_to_qbool(ret); 7817b7b7d18SPaolo Bonzini if (!qbool) { 7827b7b7d18SPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); 7837b7b7d18SPaolo Bonzini retval = false; 7847b7b7d18SPaolo Bonzini } else { 7857b7b7d18SPaolo Bonzini retval = qbool_get_int(qbool); 7867b7b7d18SPaolo Bonzini } 7877b7b7d18SPaolo Bonzini 7887b7b7d18SPaolo Bonzini QDECREF(qbool); 7897b7b7d18SPaolo Bonzini return retval; 7907b7b7d18SPaolo Bonzini } 7917b7b7d18SPaolo Bonzini 7927b7b7d18SPaolo Bonzini void object_property_set_int(Object *obj, int64_t value, 7937b7b7d18SPaolo Bonzini const char *name, Error **errp) 7947b7b7d18SPaolo Bonzini { 7957b7b7d18SPaolo Bonzini QInt *qint = qint_from_int(value); 7967b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qint), name, errp); 7977b7b7d18SPaolo Bonzini 7987b7b7d18SPaolo Bonzini QDECREF(qint); 7997b7b7d18SPaolo Bonzini } 8007b7b7d18SPaolo Bonzini 8017b7b7d18SPaolo Bonzini int64_t object_property_get_int(Object *obj, const char *name, 8027b7b7d18SPaolo Bonzini Error **errp) 8037b7b7d18SPaolo Bonzini { 8047b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 8057b7b7d18SPaolo Bonzini QInt *qint; 8067b7b7d18SPaolo Bonzini int64_t retval; 8077b7b7d18SPaolo Bonzini 8087b7b7d18SPaolo Bonzini if (!ret) { 8097b7b7d18SPaolo Bonzini return -1; 8107b7b7d18SPaolo Bonzini } 8117b7b7d18SPaolo Bonzini qint = qobject_to_qint(ret); 8127b7b7d18SPaolo Bonzini if (!qint) { 8137b7b7d18SPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); 8147b7b7d18SPaolo Bonzini retval = -1; 8157b7b7d18SPaolo Bonzini } else { 8167b7b7d18SPaolo Bonzini retval = qint_get_int(qint); 8177b7b7d18SPaolo Bonzini } 8187b7b7d18SPaolo Bonzini 8197b7b7d18SPaolo Bonzini QDECREF(qint); 8207b7b7d18SPaolo Bonzini return retval; 8217b7b7d18SPaolo Bonzini } 8227b7b7d18SPaolo Bonzini 823b2cd7deeSPaolo Bonzini void object_property_parse(Object *obj, const char *string, 824b2cd7deeSPaolo Bonzini const char *name, Error **errp) 825b2cd7deeSPaolo Bonzini { 826b2cd7deeSPaolo Bonzini StringInputVisitor *mi; 827b2cd7deeSPaolo Bonzini mi = string_input_visitor_new(string); 828b2cd7deeSPaolo Bonzini object_property_set(obj, string_input_get_visitor(mi), name, errp); 829b2cd7deeSPaolo Bonzini 830b2cd7deeSPaolo Bonzini string_input_visitor_cleanup(mi); 831b2cd7deeSPaolo Bonzini } 832b2cd7deeSPaolo Bonzini 833b2cd7deeSPaolo Bonzini char *object_property_print(Object *obj, const char *name, 834b2cd7deeSPaolo Bonzini Error **errp) 835b2cd7deeSPaolo Bonzini { 836b2cd7deeSPaolo Bonzini StringOutputVisitor *mo; 837b2cd7deeSPaolo Bonzini char *string; 838b2cd7deeSPaolo Bonzini 839b2cd7deeSPaolo Bonzini mo = string_output_visitor_new(); 8408185bfc1SPaolo Bonzini object_property_get(obj, string_output_get_visitor(mo), name, errp); 841b2cd7deeSPaolo Bonzini string = string_output_get_string(mo); 842b2cd7deeSPaolo Bonzini string_output_visitor_cleanup(mo); 843b2cd7deeSPaolo Bonzini return string; 844b2cd7deeSPaolo Bonzini } 845b2cd7deeSPaolo Bonzini 84657c9fafeSAnthony Liguori const char *object_property_get_type(Object *obj, const char *name, Error **errp) 84757c9fafeSAnthony Liguori { 84889bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 84957c9fafeSAnthony Liguori if (prop == NULL) { 85057c9fafeSAnthony Liguori return NULL; 85157c9fafeSAnthony Liguori } 85257c9fafeSAnthony Liguori 85357c9fafeSAnthony Liguori return prop->type; 85457c9fafeSAnthony Liguori } 85557c9fafeSAnthony Liguori 85657c9fafeSAnthony Liguori Object *object_get_root(void) 85757c9fafeSAnthony Liguori { 8588b45d447SAnthony Liguori static Object *root; 85957c9fafeSAnthony Liguori 8608b45d447SAnthony Liguori if (!root) { 8618b45d447SAnthony Liguori root = object_new("container"); 86257c9fafeSAnthony Liguori } 86357c9fafeSAnthony Liguori 8648b45d447SAnthony Liguori return root; 86557c9fafeSAnthony Liguori } 86657c9fafeSAnthony Liguori 86757c9fafeSAnthony Liguori static void object_get_child_property(Object *obj, Visitor *v, void *opaque, 86857c9fafeSAnthony Liguori const char *name, Error **errp) 86957c9fafeSAnthony Liguori { 87057c9fafeSAnthony Liguori Object *child = opaque; 87157c9fafeSAnthony Liguori gchar *path; 87257c9fafeSAnthony Liguori 87357c9fafeSAnthony Liguori path = object_get_canonical_path(child); 87457c9fafeSAnthony Liguori visit_type_str(v, &path, name, errp); 87557c9fafeSAnthony Liguori g_free(path); 87657c9fafeSAnthony Liguori } 87757c9fafeSAnthony Liguori 878db85b575SAnthony Liguori static void object_finalize_child_property(Object *obj, const char *name, 879db85b575SAnthony Liguori void *opaque) 880db85b575SAnthony Liguori { 881db85b575SAnthony Liguori Object *child = opaque; 882db85b575SAnthony Liguori 883db85b575SAnthony Liguori object_unref(child); 884db85b575SAnthony Liguori } 885db85b575SAnthony Liguori 88657c9fafeSAnthony Liguori void object_property_add_child(Object *obj, const char *name, 88757c9fafeSAnthony Liguori Object *child, Error **errp) 88857c9fafeSAnthony Liguori { 88957c9fafeSAnthony Liguori gchar *type; 89057c9fafeSAnthony Liguori 89157c9fafeSAnthony Liguori type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); 89257c9fafeSAnthony Liguori 89357c9fafeSAnthony Liguori object_property_add(obj, name, type, object_get_child_property, 894db85b575SAnthony Liguori NULL, object_finalize_child_property, child, errp); 89557c9fafeSAnthony Liguori 89657c9fafeSAnthony Liguori object_ref(child); 89757c9fafeSAnthony Liguori g_assert(child->parent == NULL); 89857c9fafeSAnthony Liguori child->parent = obj; 89957c9fafeSAnthony Liguori 90057c9fafeSAnthony Liguori g_free(type); 90157c9fafeSAnthony Liguori } 90257c9fafeSAnthony Liguori 90357c9fafeSAnthony Liguori static void object_get_link_property(Object *obj, Visitor *v, void *opaque, 90457c9fafeSAnthony Liguori const char *name, Error **errp) 90557c9fafeSAnthony Liguori { 90657c9fafeSAnthony Liguori Object **child = opaque; 90757c9fafeSAnthony Liguori gchar *path; 90857c9fafeSAnthony Liguori 90957c9fafeSAnthony Liguori if (*child) { 91057c9fafeSAnthony Liguori path = object_get_canonical_path(*child); 91157c9fafeSAnthony Liguori visit_type_str(v, &path, name, errp); 91257c9fafeSAnthony Liguori g_free(path); 91357c9fafeSAnthony Liguori } else { 91457c9fafeSAnthony Liguori path = (gchar *)""; 91557c9fafeSAnthony Liguori visit_type_str(v, &path, name, errp); 91657c9fafeSAnthony Liguori } 91757c9fafeSAnthony Liguori } 91857c9fafeSAnthony Liguori 91957c9fafeSAnthony Liguori static void object_set_link_property(Object *obj, Visitor *v, void *opaque, 92057c9fafeSAnthony Liguori const char *name, Error **errp) 92157c9fafeSAnthony Liguori { 92257c9fafeSAnthony Liguori Object **child = opaque; 923f0cdc966SAlexander Barabash Object *old_target; 92457c9fafeSAnthony Liguori bool ambiguous = false; 92557c9fafeSAnthony Liguori const char *type; 92657c9fafeSAnthony Liguori char *path; 92711e35bfdSPaolo Bonzini gchar *target_type; 92857c9fafeSAnthony Liguori 92957c9fafeSAnthony Liguori type = object_property_get_type(obj, name, NULL); 93057c9fafeSAnthony Liguori 93157c9fafeSAnthony Liguori visit_type_str(v, &path, name, errp); 93257c9fafeSAnthony Liguori 933f0cdc966SAlexander Barabash old_target = *child; 93411e35bfdSPaolo Bonzini *child = NULL; 93557c9fafeSAnthony Liguori 93657c9fafeSAnthony Liguori if (strcmp(path, "") != 0) { 93757c9fafeSAnthony Liguori Object *target; 93857c9fafeSAnthony Liguori 9398f770d39SPaolo Bonzini /* Go from link<FOO> to FOO. */ 94011e35bfdSPaolo Bonzini target_type = g_strndup(&type[5], strlen(type) - 6); 94111e35bfdSPaolo Bonzini target = object_resolve_path_type(path, target_type, &ambiguous); 94211e35bfdSPaolo Bonzini 94311e35bfdSPaolo Bonzini if (ambiguous) { 94411e35bfdSPaolo Bonzini error_set(errp, QERR_AMBIGUOUS_PATH, path); 94511e35bfdSPaolo Bonzini } else if (target) { 94657c9fafeSAnthony Liguori object_ref(target); 947fe40e627SAnthony Liguori *child = target; 94857c9fafeSAnthony Liguori } else { 94911e35bfdSPaolo Bonzini target = object_resolve_path(path, &ambiguous); 95011e35bfdSPaolo Bonzini if (target || ambiguous) { 95111e35bfdSPaolo Bonzini error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type); 95257c9fafeSAnthony Liguori } else { 95357c9fafeSAnthony Liguori error_set(errp, QERR_DEVICE_NOT_FOUND, path); 95457c9fafeSAnthony Liguori } 95511e35bfdSPaolo Bonzini } 95611e35bfdSPaolo Bonzini g_free(target_type); 95757c9fafeSAnthony Liguori } 95857c9fafeSAnthony Liguori 95957c9fafeSAnthony Liguori g_free(path); 960f0cdc966SAlexander Barabash 961f0cdc966SAlexander Barabash if (old_target != NULL) { 962f0cdc966SAlexander Barabash object_unref(old_target); 963f0cdc966SAlexander Barabash } 96457c9fafeSAnthony Liguori } 96557c9fafeSAnthony Liguori 96657c9fafeSAnthony Liguori void object_property_add_link(Object *obj, const char *name, 96757c9fafeSAnthony Liguori const char *type, Object **child, 96857c9fafeSAnthony Liguori Error **errp) 96957c9fafeSAnthony Liguori { 97057c9fafeSAnthony Liguori gchar *full_type; 97157c9fafeSAnthony Liguori 97257c9fafeSAnthony Liguori full_type = g_strdup_printf("link<%s>", type); 97357c9fafeSAnthony Liguori 97457c9fafeSAnthony Liguori object_property_add(obj, name, full_type, 97557c9fafeSAnthony Liguori object_get_link_property, 97657c9fafeSAnthony Liguori object_set_link_property, 97757c9fafeSAnthony Liguori NULL, child, errp); 97857c9fafeSAnthony Liguori 97957c9fafeSAnthony Liguori g_free(full_type); 98057c9fafeSAnthony Liguori } 98157c9fafeSAnthony Liguori 98257c9fafeSAnthony Liguori gchar *object_get_canonical_path(Object *obj) 98357c9fafeSAnthony Liguori { 98457c9fafeSAnthony Liguori Object *root = object_get_root(); 98557c9fafeSAnthony Liguori char *newpath = NULL, *path = NULL; 98657c9fafeSAnthony Liguori 98757c9fafeSAnthony Liguori while (obj != root) { 98857c9fafeSAnthony Liguori ObjectProperty *prop = NULL; 98957c9fafeSAnthony Liguori 99057c9fafeSAnthony Liguori g_assert(obj->parent != NULL); 99157c9fafeSAnthony Liguori 99257c9fafeSAnthony Liguori QTAILQ_FOREACH(prop, &obj->parent->properties, node) { 9935d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 99457c9fafeSAnthony Liguori continue; 99557c9fafeSAnthony Liguori } 99657c9fafeSAnthony Liguori 99757c9fafeSAnthony Liguori if (prop->opaque == obj) { 99857c9fafeSAnthony Liguori if (path) { 99957c9fafeSAnthony Liguori newpath = g_strdup_printf("%s/%s", prop->name, path); 100057c9fafeSAnthony Liguori g_free(path); 100157c9fafeSAnthony Liguori path = newpath; 100257c9fafeSAnthony Liguori } else { 100357c9fafeSAnthony Liguori path = g_strdup(prop->name); 100457c9fafeSAnthony Liguori } 100557c9fafeSAnthony Liguori break; 100657c9fafeSAnthony Liguori } 100757c9fafeSAnthony Liguori } 100857c9fafeSAnthony Liguori 100957c9fafeSAnthony Liguori g_assert(prop != NULL); 101057c9fafeSAnthony Liguori 101157c9fafeSAnthony Liguori obj = obj->parent; 101257c9fafeSAnthony Liguori } 101357c9fafeSAnthony Liguori 101457c9fafeSAnthony Liguori newpath = g_strdup_printf("/%s", path); 101557c9fafeSAnthony Liguori g_free(path); 101657c9fafeSAnthony Liguori 101757c9fafeSAnthony Liguori return newpath; 101857c9fafeSAnthony Liguori } 101957c9fafeSAnthony Liguori 1020*3e84b483SAndreas Färber Object *object_resolve_path_component(Object *parent, const gchar *part) 1021a612b2a6SPaolo Bonzini { 102289bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(parent, part, NULL); 1023a612b2a6SPaolo Bonzini if (prop == NULL) { 1024a612b2a6SPaolo Bonzini return NULL; 1025a612b2a6SPaolo Bonzini } 1026a612b2a6SPaolo Bonzini 10275d9d3f47SAndreas Färber if (object_property_is_link(prop)) { 1028a612b2a6SPaolo Bonzini return *(Object **)prop->opaque; 10295d9d3f47SAndreas Färber } else if (object_property_is_child(prop)) { 1030a612b2a6SPaolo Bonzini return prop->opaque; 1031a612b2a6SPaolo Bonzini } else { 1032a612b2a6SPaolo Bonzini return NULL; 1033a612b2a6SPaolo Bonzini } 1034a612b2a6SPaolo Bonzini } 1035a612b2a6SPaolo Bonzini 103657c9fafeSAnthony Liguori static Object *object_resolve_abs_path(Object *parent, 103757c9fafeSAnthony Liguori gchar **parts, 103802fe2db6SPaolo Bonzini const char *typename, 103957c9fafeSAnthony Liguori int index) 104057c9fafeSAnthony Liguori { 104157c9fafeSAnthony Liguori Object *child; 104257c9fafeSAnthony Liguori 104357c9fafeSAnthony Liguori if (parts[index] == NULL) { 104402fe2db6SPaolo Bonzini return object_dynamic_cast(parent, typename); 104557c9fafeSAnthony Liguori } 104657c9fafeSAnthony Liguori 104757c9fafeSAnthony Liguori if (strcmp(parts[index], "") == 0) { 104802fe2db6SPaolo Bonzini return object_resolve_abs_path(parent, parts, typename, index + 1); 104957c9fafeSAnthony Liguori } 105057c9fafeSAnthony Liguori 1051a612b2a6SPaolo Bonzini child = object_resolve_path_component(parent, parts[index]); 105257c9fafeSAnthony Liguori if (!child) { 105357c9fafeSAnthony Liguori return NULL; 105457c9fafeSAnthony Liguori } 105557c9fafeSAnthony Liguori 105602fe2db6SPaolo Bonzini return object_resolve_abs_path(child, parts, typename, index + 1); 105757c9fafeSAnthony Liguori } 105857c9fafeSAnthony Liguori 105957c9fafeSAnthony Liguori static Object *object_resolve_partial_path(Object *parent, 106057c9fafeSAnthony Liguori gchar **parts, 106102fe2db6SPaolo Bonzini const char *typename, 106257c9fafeSAnthony Liguori bool *ambiguous) 106357c9fafeSAnthony Liguori { 106457c9fafeSAnthony Liguori Object *obj; 106557c9fafeSAnthony Liguori ObjectProperty *prop; 106657c9fafeSAnthony Liguori 106702fe2db6SPaolo Bonzini obj = object_resolve_abs_path(parent, parts, typename, 0); 106857c9fafeSAnthony Liguori 106957c9fafeSAnthony Liguori QTAILQ_FOREACH(prop, &parent->properties, node) { 107057c9fafeSAnthony Liguori Object *found; 107157c9fafeSAnthony Liguori 10725d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 107357c9fafeSAnthony Liguori continue; 107457c9fafeSAnthony Liguori } 107557c9fafeSAnthony Liguori 107602fe2db6SPaolo Bonzini found = object_resolve_partial_path(prop->opaque, parts, 107702fe2db6SPaolo Bonzini typename, ambiguous); 107857c9fafeSAnthony Liguori if (found) { 107957c9fafeSAnthony Liguori if (obj) { 108057c9fafeSAnthony Liguori if (ambiguous) { 108157c9fafeSAnthony Liguori *ambiguous = true; 108257c9fafeSAnthony Liguori } 108357c9fafeSAnthony Liguori return NULL; 108457c9fafeSAnthony Liguori } 108557c9fafeSAnthony Liguori obj = found; 108657c9fafeSAnthony Liguori } 108757c9fafeSAnthony Liguori 108857c9fafeSAnthony Liguori if (ambiguous && *ambiguous) { 108957c9fafeSAnthony Liguori return NULL; 109057c9fafeSAnthony Liguori } 109157c9fafeSAnthony Liguori } 109257c9fafeSAnthony Liguori 109357c9fafeSAnthony Liguori return obj; 109457c9fafeSAnthony Liguori } 109557c9fafeSAnthony Liguori 109602fe2db6SPaolo Bonzini Object *object_resolve_path_type(const char *path, const char *typename, 109702fe2db6SPaolo Bonzini bool *ambiguous) 109857c9fafeSAnthony Liguori { 109957c9fafeSAnthony Liguori bool partial_path = true; 110057c9fafeSAnthony Liguori Object *obj; 110157c9fafeSAnthony Liguori gchar **parts; 110257c9fafeSAnthony Liguori 110357c9fafeSAnthony Liguori parts = g_strsplit(path, "/", 0); 110457c9fafeSAnthony Liguori if (parts == NULL || parts[0] == NULL) { 110557c9fafeSAnthony Liguori g_strfreev(parts); 110657c9fafeSAnthony Liguori return object_get_root(); 110757c9fafeSAnthony Liguori } 110857c9fafeSAnthony Liguori 110957c9fafeSAnthony Liguori if (strcmp(parts[0], "") == 0) { 111057c9fafeSAnthony Liguori partial_path = false; 111157c9fafeSAnthony Liguori } 111257c9fafeSAnthony Liguori 111357c9fafeSAnthony Liguori if (partial_path) { 111457c9fafeSAnthony Liguori if (ambiguous) { 111557c9fafeSAnthony Liguori *ambiguous = false; 111657c9fafeSAnthony Liguori } 111702fe2db6SPaolo Bonzini obj = object_resolve_partial_path(object_get_root(), parts, 111802fe2db6SPaolo Bonzini typename, ambiguous); 111957c9fafeSAnthony Liguori } else { 112002fe2db6SPaolo Bonzini obj = object_resolve_abs_path(object_get_root(), parts, typename, 1); 112157c9fafeSAnthony Liguori } 112257c9fafeSAnthony Liguori 112357c9fafeSAnthony Liguori g_strfreev(parts); 112457c9fafeSAnthony Liguori 112557c9fafeSAnthony Liguori return obj; 112657c9fafeSAnthony Liguori } 112757c9fafeSAnthony Liguori 112802fe2db6SPaolo Bonzini Object *object_resolve_path(const char *path, bool *ambiguous) 112902fe2db6SPaolo Bonzini { 113002fe2db6SPaolo Bonzini return object_resolve_path_type(path, TYPE_OBJECT, ambiguous); 113102fe2db6SPaolo Bonzini } 113202fe2db6SPaolo Bonzini 113357c9fafeSAnthony Liguori typedef struct StringProperty 113457c9fafeSAnthony Liguori { 113557c9fafeSAnthony Liguori char *(*get)(Object *, Error **); 113657c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **); 113757c9fafeSAnthony Liguori } StringProperty; 113857c9fafeSAnthony Liguori 11397b7b7d18SPaolo Bonzini static void property_get_str(Object *obj, Visitor *v, void *opaque, 114057c9fafeSAnthony Liguori const char *name, Error **errp) 114157c9fafeSAnthony Liguori { 114257c9fafeSAnthony Liguori StringProperty *prop = opaque; 114357c9fafeSAnthony Liguori char *value; 114457c9fafeSAnthony Liguori 114557c9fafeSAnthony Liguori value = prop->get(obj, errp); 114657c9fafeSAnthony Liguori if (value) { 114757c9fafeSAnthony Liguori visit_type_str(v, &value, name, errp); 114857c9fafeSAnthony Liguori g_free(value); 114957c9fafeSAnthony Liguori } 115057c9fafeSAnthony Liguori } 115157c9fafeSAnthony Liguori 11527b7b7d18SPaolo Bonzini static void property_set_str(Object *obj, Visitor *v, void *opaque, 115357c9fafeSAnthony Liguori const char *name, Error **errp) 115457c9fafeSAnthony Liguori { 115557c9fafeSAnthony Liguori StringProperty *prop = opaque; 115657c9fafeSAnthony Liguori char *value; 115757c9fafeSAnthony Liguori Error *local_err = NULL; 115857c9fafeSAnthony Liguori 115957c9fafeSAnthony Liguori visit_type_str(v, &value, name, &local_err); 116057c9fafeSAnthony Liguori if (local_err) { 116157c9fafeSAnthony Liguori error_propagate(errp, local_err); 116257c9fafeSAnthony Liguori return; 116357c9fafeSAnthony Liguori } 116457c9fafeSAnthony Liguori 116557c9fafeSAnthony Liguori prop->set(obj, value, errp); 116657c9fafeSAnthony Liguori g_free(value); 116757c9fafeSAnthony Liguori } 116857c9fafeSAnthony Liguori 11697b7b7d18SPaolo Bonzini static void property_release_str(Object *obj, const char *name, 117057c9fafeSAnthony Liguori void *opaque) 117157c9fafeSAnthony Liguori { 117257c9fafeSAnthony Liguori StringProperty *prop = opaque; 117357c9fafeSAnthony Liguori g_free(prop); 117457c9fafeSAnthony Liguori } 117557c9fafeSAnthony Liguori 117657c9fafeSAnthony Liguori void object_property_add_str(Object *obj, const char *name, 117757c9fafeSAnthony Liguori char *(*get)(Object *, Error **), 117857c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **), 117957c9fafeSAnthony Liguori Error **errp) 118057c9fafeSAnthony Liguori { 118157c9fafeSAnthony Liguori StringProperty *prop = g_malloc0(sizeof(*prop)); 118257c9fafeSAnthony Liguori 118357c9fafeSAnthony Liguori prop->get = get; 118457c9fafeSAnthony Liguori prop->set = set; 118557c9fafeSAnthony Liguori 118657c9fafeSAnthony Liguori object_property_add(obj, name, "string", 11877b7b7d18SPaolo Bonzini get ? property_get_str : NULL, 11887b7b7d18SPaolo Bonzini set ? property_set_str : NULL, 11897b7b7d18SPaolo Bonzini property_release_str, 119057c9fafeSAnthony Liguori prop, errp); 119157c9fafeSAnthony Liguori } 1192745549c8SPaolo Bonzini 11930e558843SAnthony Liguori typedef struct BoolProperty 11940e558843SAnthony Liguori { 11950e558843SAnthony Liguori bool (*get)(Object *, Error **); 11960e558843SAnthony Liguori void (*set)(Object *, bool, Error **); 11970e558843SAnthony Liguori } BoolProperty; 11980e558843SAnthony Liguori 11990e558843SAnthony Liguori static void property_get_bool(Object *obj, Visitor *v, void *opaque, 12000e558843SAnthony Liguori const char *name, Error **errp) 12010e558843SAnthony Liguori { 12020e558843SAnthony Liguori BoolProperty *prop = opaque; 12030e558843SAnthony Liguori bool value; 12040e558843SAnthony Liguori 12050e558843SAnthony Liguori value = prop->get(obj, errp); 12060e558843SAnthony Liguori visit_type_bool(v, &value, name, errp); 12070e558843SAnthony Liguori } 12080e558843SAnthony Liguori 12090e558843SAnthony Liguori static void property_set_bool(Object *obj, Visitor *v, void *opaque, 12100e558843SAnthony Liguori const char *name, Error **errp) 12110e558843SAnthony Liguori { 12120e558843SAnthony Liguori BoolProperty *prop = opaque; 12130e558843SAnthony Liguori bool value; 12140e558843SAnthony Liguori Error *local_err = NULL; 12150e558843SAnthony Liguori 12160e558843SAnthony Liguori visit_type_bool(v, &value, name, &local_err); 12170e558843SAnthony Liguori if (local_err) { 12180e558843SAnthony Liguori error_propagate(errp, local_err); 12190e558843SAnthony Liguori return; 12200e558843SAnthony Liguori } 12210e558843SAnthony Liguori 12220e558843SAnthony Liguori prop->set(obj, value, errp); 12230e558843SAnthony Liguori } 12240e558843SAnthony Liguori 12250e558843SAnthony Liguori static void property_release_bool(Object *obj, const char *name, 12260e558843SAnthony Liguori void *opaque) 12270e558843SAnthony Liguori { 12280e558843SAnthony Liguori BoolProperty *prop = opaque; 12290e558843SAnthony Liguori g_free(prop); 12300e558843SAnthony Liguori } 12310e558843SAnthony Liguori 12320e558843SAnthony Liguori void object_property_add_bool(Object *obj, const char *name, 12330e558843SAnthony Liguori bool (*get)(Object *, Error **), 12340e558843SAnthony Liguori void (*set)(Object *, bool, Error **), 12350e558843SAnthony Liguori Error **errp) 12360e558843SAnthony Liguori { 12370e558843SAnthony Liguori BoolProperty *prop = g_malloc0(sizeof(*prop)); 12380e558843SAnthony Liguori 12390e558843SAnthony Liguori prop->get = get; 12400e558843SAnthony Liguori prop->set = set; 12410e558843SAnthony Liguori 12420e558843SAnthony Liguori object_property_add(obj, name, "bool", 12430e558843SAnthony Liguori get ? property_get_bool : NULL, 12440e558843SAnthony Liguori set ? property_set_bool : NULL, 12450e558843SAnthony Liguori property_release_bool, 12460e558843SAnthony Liguori prop, errp); 12470e558843SAnthony Liguori } 12480e558843SAnthony Liguori 12492f262e06SPaolo Bonzini static char *qdev_get_type(Object *obj, Error **errp) 12502f262e06SPaolo Bonzini { 12512f262e06SPaolo Bonzini return g_strdup(object_get_typename(obj)); 12522f262e06SPaolo Bonzini } 12532f262e06SPaolo Bonzini 12542f262e06SPaolo Bonzini static void object_instance_init(Object *obj) 12552f262e06SPaolo Bonzini { 12562f262e06SPaolo Bonzini object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); 12572f262e06SPaolo Bonzini } 12582f262e06SPaolo Bonzini 1259745549c8SPaolo Bonzini static void register_types(void) 1260745549c8SPaolo Bonzini { 1261745549c8SPaolo Bonzini static TypeInfo interface_info = { 1262745549c8SPaolo Bonzini .name = TYPE_INTERFACE, 126333e95c63SAnthony Liguori .class_size = sizeof(InterfaceClass), 1264745549c8SPaolo Bonzini .abstract = true, 1265745549c8SPaolo Bonzini }; 1266745549c8SPaolo Bonzini 1267745549c8SPaolo Bonzini static TypeInfo object_info = { 1268745549c8SPaolo Bonzini .name = TYPE_OBJECT, 1269745549c8SPaolo Bonzini .instance_size = sizeof(Object), 12702f262e06SPaolo Bonzini .instance_init = object_instance_init, 1271745549c8SPaolo Bonzini .abstract = true, 1272745549c8SPaolo Bonzini }; 1273745549c8SPaolo Bonzini 1274049cb3cfSPaolo Bonzini type_interface = type_register_internal(&interface_info); 1275049cb3cfSPaolo Bonzini type_register_internal(&object_info); 1276745549c8SPaolo Bonzini } 1277745549c8SPaolo Bonzini 1278745549c8SPaolo Bonzini type_init(register_types) 1279