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 139bbc853bSPeter Maydell #include "qemu/osdep.h" 14da34e65cSMarkus Armbruster #include "qapi/error.h" 1514cccb61SPaolo Bonzini #include "qom/object.h" 16a31bdae5SDaniel P. Berrange #include "qom/object_interfaces.h" 17f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 187b1b5d19SPaolo Bonzini #include "qapi/visitor.h" 19b2cd7deeSPaolo Bonzini #include "qapi/string-input-visitor.h" 20b2cd7deeSPaolo Bonzini #include "qapi/string-output-visitor.h" 21eb815e24SMarkus Armbruster #include "qapi/qapi-builtin-visit.h" 227b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h" 23fa131d94SPaolo Bonzini #include "trace.h" 242f28d2ffSAnthony Liguori 257b7b7d18SPaolo Bonzini /* TODO: replace QObject with a simpler visitor to avoid a dependency 267b7b7d18SPaolo Bonzini * of the QOM core on QObject? */ 2714cccb61SPaolo Bonzini #include "qom/qom-qobject.h" 287b1b5d19SPaolo Bonzini #include "qapi/qmp/qbool.h" 2915280c36SMarkus Armbruster #include "qapi/qmp/qnum.h" 307b1b5d19SPaolo Bonzini #include "qapi/qmp/qstring.h" 317b7b7d18SPaolo Bonzini 322f28d2ffSAnthony Liguori #define MAX_INTERFACES 32 332f28d2ffSAnthony Liguori 342f28d2ffSAnthony Liguori typedef struct InterfaceImpl InterfaceImpl; 352f28d2ffSAnthony Liguori typedef struct TypeImpl TypeImpl; 362f28d2ffSAnthony Liguori 372f28d2ffSAnthony Liguori struct InterfaceImpl 382f28d2ffSAnthony Liguori { 3933e95c63SAnthony Liguori const char *typename; 402f28d2ffSAnthony Liguori }; 412f28d2ffSAnthony Liguori 422f28d2ffSAnthony Liguori struct TypeImpl 432f28d2ffSAnthony Liguori { 442f28d2ffSAnthony Liguori const char *name; 452f28d2ffSAnthony Liguori 462f28d2ffSAnthony Liguori size_t class_size; 472f28d2ffSAnthony Liguori 482f28d2ffSAnthony Liguori size_t instance_size; 492f28d2ffSAnthony Liguori 502f28d2ffSAnthony Liguori void (*class_init)(ObjectClass *klass, void *data); 513b50e311SPaolo Bonzini void (*class_base_init)(ObjectClass *klass, void *data); 522f28d2ffSAnthony Liguori void (*class_finalize)(ObjectClass *klass, void *data); 532f28d2ffSAnthony Liguori 542f28d2ffSAnthony Liguori void *class_data; 552f28d2ffSAnthony Liguori 562f28d2ffSAnthony Liguori void (*instance_init)(Object *obj); 578231c2ddSEduardo Habkost void (*instance_post_init)(Object *obj); 582f28d2ffSAnthony Liguori void (*instance_finalize)(Object *obj); 592f28d2ffSAnthony Liguori 602f28d2ffSAnthony Liguori bool abstract; 612f28d2ffSAnthony Liguori 622f28d2ffSAnthony Liguori const char *parent; 632f28d2ffSAnthony Liguori TypeImpl *parent_type; 642f28d2ffSAnthony Liguori 652f28d2ffSAnthony Liguori ObjectClass *class; 662f28d2ffSAnthony Liguori 672f28d2ffSAnthony Liguori int num_interfaces; 682f28d2ffSAnthony Liguori InterfaceImpl interfaces[MAX_INTERFACES]; 692f28d2ffSAnthony Liguori }; 702f28d2ffSAnthony Liguori 719970bd88SPaolo Bonzini static Type type_interface; 729970bd88SPaolo Bonzini 732f28d2ffSAnthony Liguori static GHashTable *type_table_get(void) 742f28d2ffSAnthony Liguori { 752f28d2ffSAnthony Liguori static GHashTable *type_table; 762f28d2ffSAnthony Liguori 772f28d2ffSAnthony Liguori if (type_table == NULL) { 782f28d2ffSAnthony Liguori type_table = g_hash_table_new(g_str_hash, g_str_equal); 792f28d2ffSAnthony Liguori } 802f28d2ffSAnthony Liguori 812f28d2ffSAnthony Liguori return type_table; 822f28d2ffSAnthony Liguori } 832f28d2ffSAnthony Liguori 84f54c19caSHervé Poussineau static bool enumerating_types; 85f54c19caSHervé Poussineau 862f28d2ffSAnthony Liguori static void type_table_add(TypeImpl *ti) 872f28d2ffSAnthony Liguori { 88f54c19caSHervé Poussineau assert(!enumerating_types); 892f28d2ffSAnthony Liguori g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 902f28d2ffSAnthony Liguori } 912f28d2ffSAnthony Liguori 922f28d2ffSAnthony Liguori static TypeImpl *type_table_lookup(const char *name) 932f28d2ffSAnthony Liguori { 942f28d2ffSAnthony Liguori return g_hash_table_lookup(type_table_get(), name); 952f28d2ffSAnthony Liguori } 962f28d2ffSAnthony Liguori 97b061dc41SPaolo Bonzini static TypeImpl *type_new(const TypeInfo *info) 982f28d2ffSAnthony Liguori { 992f28d2ffSAnthony Liguori TypeImpl *ti = g_malloc0(sizeof(*ti)); 10033e95c63SAnthony Liguori int i; 1012f28d2ffSAnthony Liguori 1022f28d2ffSAnthony Liguori g_assert(info->name != NULL); 1032f28d2ffSAnthony Liguori 10473093354SAnthony Liguori if (type_table_lookup(info->name) != NULL) { 10573093354SAnthony Liguori fprintf(stderr, "Registering `%s' which already exists\n", info->name); 10673093354SAnthony Liguori abort(); 10773093354SAnthony Liguori } 10873093354SAnthony Liguori 1092f28d2ffSAnthony Liguori ti->name = g_strdup(info->name); 1102f28d2ffSAnthony Liguori ti->parent = g_strdup(info->parent); 1112f28d2ffSAnthony Liguori 1122f28d2ffSAnthony Liguori ti->class_size = info->class_size; 1132f28d2ffSAnthony Liguori ti->instance_size = info->instance_size; 1142f28d2ffSAnthony Liguori 1152f28d2ffSAnthony Liguori ti->class_init = info->class_init; 1163b50e311SPaolo Bonzini ti->class_base_init = info->class_base_init; 1172f28d2ffSAnthony Liguori ti->class_finalize = info->class_finalize; 1182f28d2ffSAnthony Liguori ti->class_data = info->class_data; 1192f28d2ffSAnthony Liguori 1202f28d2ffSAnthony Liguori ti->instance_init = info->instance_init; 1218231c2ddSEduardo Habkost ti->instance_post_init = info->instance_post_init; 1222f28d2ffSAnthony Liguori ti->instance_finalize = info->instance_finalize; 1232f28d2ffSAnthony Liguori 1242f28d2ffSAnthony Liguori ti->abstract = info->abstract; 1252f28d2ffSAnthony Liguori 12633e95c63SAnthony Liguori for (i = 0; info->interfaces && info->interfaces[i].type; i++) { 12733e95c63SAnthony Liguori ti->interfaces[i].typename = g_strdup(info->interfaces[i].type); 1282f28d2ffSAnthony Liguori } 12933e95c63SAnthony Liguori ti->num_interfaces = i; 1302f28d2ffSAnthony Liguori 131b061dc41SPaolo Bonzini return ti; 132b061dc41SPaolo Bonzini } 1332f28d2ffSAnthony Liguori 134b061dc41SPaolo Bonzini static TypeImpl *type_register_internal(const TypeInfo *info) 135b061dc41SPaolo Bonzini { 136b061dc41SPaolo Bonzini TypeImpl *ti; 137b061dc41SPaolo Bonzini ti = type_new(info); 138b061dc41SPaolo Bonzini 139b061dc41SPaolo Bonzini type_table_add(ti); 1402f28d2ffSAnthony Liguori return ti; 1412f28d2ffSAnthony Liguori } 1422f28d2ffSAnthony Liguori 143049cb3cfSPaolo Bonzini TypeImpl *type_register(const TypeInfo *info) 144049cb3cfSPaolo Bonzini { 145049cb3cfSPaolo Bonzini assert(info->parent); 146049cb3cfSPaolo Bonzini return type_register_internal(info); 147049cb3cfSPaolo Bonzini } 148049cb3cfSPaolo Bonzini 1492f28d2ffSAnthony Liguori TypeImpl *type_register_static(const TypeInfo *info) 1502f28d2ffSAnthony Liguori { 1512f28d2ffSAnthony Liguori return type_register(info); 1522f28d2ffSAnthony Liguori } 1532f28d2ffSAnthony Liguori 154aa04c9d2SIgor Mammedov void type_register_static_array(const TypeInfo *infos, int nr_infos) 155aa04c9d2SIgor Mammedov { 156aa04c9d2SIgor Mammedov int i; 157aa04c9d2SIgor Mammedov 158aa04c9d2SIgor Mammedov for (i = 0; i < nr_infos; i++) { 159aa04c9d2SIgor Mammedov type_register_static(&infos[i]); 160aa04c9d2SIgor Mammedov } 161aa04c9d2SIgor Mammedov } 162aa04c9d2SIgor Mammedov 1632f28d2ffSAnthony Liguori static TypeImpl *type_get_by_name(const char *name) 1642f28d2ffSAnthony Liguori { 1652f28d2ffSAnthony Liguori if (name == NULL) { 1662f28d2ffSAnthony Liguori return NULL; 1672f28d2ffSAnthony Liguori } 1682f28d2ffSAnthony Liguori 1692f28d2ffSAnthony Liguori return type_table_lookup(name); 1702f28d2ffSAnthony Liguori } 1712f28d2ffSAnthony Liguori 1722f28d2ffSAnthony Liguori static TypeImpl *type_get_parent(TypeImpl *type) 1732f28d2ffSAnthony Liguori { 1742f28d2ffSAnthony Liguori if (!type->parent_type && type->parent) { 1752f28d2ffSAnthony Liguori type->parent_type = type_get_by_name(type->parent); 1762f28d2ffSAnthony Liguori g_assert(type->parent_type != NULL); 1772f28d2ffSAnthony Liguori } 1782f28d2ffSAnthony Liguori 1792f28d2ffSAnthony Liguori return type->parent_type; 1802f28d2ffSAnthony Liguori } 1812f28d2ffSAnthony Liguori 1822f28d2ffSAnthony Liguori static bool type_has_parent(TypeImpl *type) 1832f28d2ffSAnthony Liguori { 1842f28d2ffSAnthony Liguori return (type->parent != NULL); 1852f28d2ffSAnthony Liguori } 1862f28d2ffSAnthony Liguori 1872f28d2ffSAnthony Liguori static size_t type_class_get_size(TypeImpl *ti) 1882f28d2ffSAnthony Liguori { 1892f28d2ffSAnthony Liguori if (ti->class_size) { 1902f28d2ffSAnthony Liguori return ti->class_size; 1912f28d2ffSAnthony Liguori } 1922f28d2ffSAnthony Liguori 1932f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 1942f28d2ffSAnthony Liguori return type_class_get_size(type_get_parent(ti)); 1952f28d2ffSAnthony Liguori } 1962f28d2ffSAnthony Liguori 1972f28d2ffSAnthony Liguori return sizeof(ObjectClass); 1982f28d2ffSAnthony Liguori } 1992f28d2ffSAnthony Liguori 200aca59af6SIgor Mitsyanko static size_t type_object_get_size(TypeImpl *ti) 201aca59af6SIgor Mitsyanko { 202aca59af6SIgor Mitsyanko if (ti->instance_size) { 203aca59af6SIgor Mitsyanko return ti->instance_size; 204aca59af6SIgor Mitsyanko } 205aca59af6SIgor Mitsyanko 206aca59af6SIgor Mitsyanko if (type_has_parent(ti)) { 207aca59af6SIgor Mitsyanko return type_object_get_size(type_get_parent(ti)); 208aca59af6SIgor Mitsyanko } 209aca59af6SIgor Mitsyanko 210aca59af6SIgor Mitsyanko return 0; 211aca59af6SIgor Mitsyanko } 212aca59af6SIgor Mitsyanko 2133f97b53aSBharata B Rao size_t object_type_get_instance_size(const char *typename) 2143f97b53aSBharata B Rao { 2153f97b53aSBharata B Rao TypeImpl *type = type_get_by_name(typename); 2163f97b53aSBharata B Rao 2173f97b53aSBharata B Rao g_assert(type != NULL); 2183f97b53aSBharata B Rao return type_object_get_size(type); 2193f97b53aSBharata B Rao } 2203f97b53aSBharata B Rao 22133e95c63SAnthony Liguori static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 2222f28d2ffSAnthony Liguori { 22333e95c63SAnthony Liguori assert(target_type); 2242f28d2ffSAnthony Liguori 225b30d8054SCao jin /* Check if target_type is a direct ancestor of type */ 22633e95c63SAnthony Liguori while (type) { 22733e95c63SAnthony Liguori if (type == target_type) { 22833e95c63SAnthony Liguori return true; 22933e95c63SAnthony Liguori } 23033e95c63SAnthony Liguori 23133e95c63SAnthony Liguori type = type_get_parent(type); 23233e95c63SAnthony Liguori } 23333e95c63SAnthony Liguori 23433e95c63SAnthony Liguori return false; 23533e95c63SAnthony Liguori } 23633e95c63SAnthony Liguori 23733e95c63SAnthony Liguori static void type_initialize(TypeImpl *ti); 23833e95c63SAnthony Liguori 239b061dc41SPaolo Bonzini static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, 240b061dc41SPaolo Bonzini TypeImpl *parent_type) 24133e95c63SAnthony Liguori { 24233e95c63SAnthony Liguori InterfaceClass *new_iface; 24333e95c63SAnthony Liguori TypeInfo info = { }; 24433e95c63SAnthony Liguori TypeImpl *iface_impl; 24533e95c63SAnthony Liguori 246b061dc41SPaolo Bonzini info.parent = parent_type->name; 247b061dc41SPaolo Bonzini info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name); 24833e95c63SAnthony Liguori info.abstract = true; 24933e95c63SAnthony Liguori 250b061dc41SPaolo Bonzini iface_impl = type_new(&info); 251b061dc41SPaolo Bonzini iface_impl->parent_type = parent_type; 25233e95c63SAnthony Liguori type_initialize(iface_impl); 25333e95c63SAnthony Liguori g_free((char *)info.name); 25433e95c63SAnthony Liguori 25533e95c63SAnthony Liguori new_iface = (InterfaceClass *)iface_impl->class; 25633e95c63SAnthony Liguori new_iface->concrete_class = ti->class; 257b061dc41SPaolo Bonzini new_iface->interface_type = interface_type; 25833e95c63SAnthony Liguori 25933e95c63SAnthony Liguori ti->class->interfaces = g_slist_append(ti->class->interfaces, 26033e95c63SAnthony Liguori iface_impl->class); 2612f28d2ffSAnthony Liguori } 2622f28d2ffSAnthony Liguori 26316bf7f52SDaniel P. Berrange static void object_property_free(gpointer data) 26416bf7f52SDaniel P. Berrange { 26516bf7f52SDaniel P. Berrange ObjectProperty *prop = data; 26616bf7f52SDaniel P. Berrange 26716bf7f52SDaniel P. Berrange g_free(prop->name); 26816bf7f52SDaniel P. Berrange g_free(prop->type); 26916bf7f52SDaniel P. Berrange g_free(prop->description); 27016bf7f52SDaniel P. Berrange g_free(prop); 27116bf7f52SDaniel P. Berrange } 27216bf7f52SDaniel P. Berrange 273ac451033SIgor Mitsyanko static void type_initialize(TypeImpl *ti) 2742f28d2ffSAnthony Liguori { 275745549c8SPaolo Bonzini TypeImpl *parent; 2762f28d2ffSAnthony Liguori 2772f28d2ffSAnthony Liguori if (ti->class) { 2782f28d2ffSAnthony Liguori return; 2792f28d2ffSAnthony Liguori } 2802f28d2ffSAnthony Liguori 2812f28d2ffSAnthony Liguori ti->class_size = type_class_get_size(ti); 282aca59af6SIgor Mitsyanko ti->instance_size = type_object_get_size(ti); 2831c6d75d5SEduardo Habkost /* Any type with zero instance_size is implicitly abstract. 2841c6d75d5SEduardo Habkost * This means interface types are all abstract. 2851c6d75d5SEduardo Habkost */ 2861c6d75d5SEduardo Habkost if (ti->instance_size == 0) { 2871c6d75d5SEduardo Habkost ti->abstract = true; 2881c6d75d5SEduardo Habkost } 2892f28d2ffSAnthony Liguori 2902f28d2ffSAnthony Liguori ti->class = g_malloc0(ti->class_size); 2912f28d2ffSAnthony Liguori 292745549c8SPaolo Bonzini parent = type_get_parent(ti); 293745549c8SPaolo Bonzini if (parent) { 294ac451033SIgor Mitsyanko type_initialize(parent); 29533e95c63SAnthony Liguori GSList *e; 29633e95c63SAnthony Liguori int i; 2972f28d2ffSAnthony Liguori 2988438a135SAndreas Färber g_assert_cmpint(parent->class_size, <=, ti->class_size); 299745549c8SPaolo Bonzini memcpy(ti->class, parent->class, parent->class_size); 3003e407de4SPeter Crosthwaite ti->class->interfaces = NULL; 30116bf7f52SDaniel P. Berrange ti->class->properties = g_hash_table_new_full( 30216bf7f52SDaniel P. Berrange g_str_hash, g_str_equal, g_free, object_property_free); 30333e95c63SAnthony Liguori 30433e95c63SAnthony Liguori for (e = parent->class->interfaces; e; e = e->next) { 305b061dc41SPaolo Bonzini InterfaceClass *iface = e->data; 306b061dc41SPaolo Bonzini ObjectClass *klass = OBJECT_CLASS(iface); 307b061dc41SPaolo Bonzini 308b061dc41SPaolo Bonzini type_initialize_interface(ti, iface->interface_type, klass->type); 30933e95c63SAnthony Liguori } 31033e95c63SAnthony Liguori 31133e95c63SAnthony Liguori for (i = 0; i < ti->num_interfaces; i++) { 31233e95c63SAnthony Liguori TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); 31333e95c63SAnthony Liguori for (e = ti->class->interfaces; e; e = e->next) { 31433e95c63SAnthony Liguori TypeImpl *target_type = OBJECT_CLASS(e->data)->type; 31533e95c63SAnthony Liguori 31633e95c63SAnthony Liguori if (type_is_ancestor(target_type, t)) { 31733e95c63SAnthony Liguori break; 31833e95c63SAnthony Liguori } 31933e95c63SAnthony Liguori } 32033e95c63SAnthony Liguori 32133e95c63SAnthony Liguori if (e) { 32233e95c63SAnthony Liguori continue; 32333e95c63SAnthony Liguori } 32433e95c63SAnthony Liguori 325b061dc41SPaolo Bonzini type_initialize_interface(ti, t, t); 32633e95c63SAnthony Liguori } 32716bf7f52SDaniel P. Berrange } else { 32816bf7f52SDaniel P. Berrange ti->class->properties = g_hash_table_new_full( 32916bf7f52SDaniel P. Berrange g_str_hash, g_str_equal, g_free, object_property_free); 330745549c8SPaolo Bonzini } 3312f28d2ffSAnthony Liguori 332745549c8SPaolo Bonzini ti->class->type = ti; 3333b50e311SPaolo Bonzini 3343b50e311SPaolo Bonzini while (parent) { 3353b50e311SPaolo Bonzini if (parent->class_base_init) { 3363b50e311SPaolo Bonzini parent->class_base_init(ti->class, ti->class_data); 3373b50e311SPaolo Bonzini } 3383b50e311SPaolo Bonzini parent = type_get_parent(parent); 3393b50e311SPaolo Bonzini } 3402f28d2ffSAnthony Liguori 3412f28d2ffSAnthony Liguori if (ti->class_init) { 3422f28d2ffSAnthony Liguori ti->class_init(ti->class, ti->class_data); 3432f28d2ffSAnthony Liguori } 3442f28d2ffSAnthony Liguori } 3452f28d2ffSAnthony Liguori 3462f28d2ffSAnthony Liguori static void object_init_with_type(Object *obj, TypeImpl *ti) 3472f28d2ffSAnthony Liguori { 3482f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 3492f28d2ffSAnthony Liguori object_init_with_type(obj, type_get_parent(ti)); 3502f28d2ffSAnthony Liguori } 3512f28d2ffSAnthony Liguori 3522f28d2ffSAnthony Liguori if (ti->instance_init) { 3532f28d2ffSAnthony Liguori ti->instance_init(obj); 3542f28d2ffSAnthony Liguori } 3552f28d2ffSAnthony Liguori } 3562f28d2ffSAnthony Liguori 3578231c2ddSEduardo Habkost static void object_post_init_with_type(Object *obj, TypeImpl *ti) 3588231c2ddSEduardo Habkost { 3598231c2ddSEduardo Habkost if (ti->instance_post_init) { 3608231c2ddSEduardo Habkost ti->instance_post_init(obj); 3618231c2ddSEduardo Habkost } 3628231c2ddSEduardo Habkost 3638231c2ddSEduardo Habkost if (type_has_parent(ti)) { 3648231c2ddSEduardo Habkost object_post_init_with_type(obj, type_get_parent(ti)); 3658231c2ddSEduardo Habkost } 3668231c2ddSEduardo Habkost } 3678231c2ddSEduardo Habkost 36863f7b10bSMarc-André Lureau static void object_initialize_with_type(void *data, size_t size, TypeImpl *type) 3692f28d2ffSAnthony Liguori { 3702f28d2ffSAnthony Liguori Object *obj = data; 3712f28d2ffSAnthony Liguori 3722f28d2ffSAnthony Liguori g_assert(type != NULL); 373ac451033SIgor Mitsyanko type_initialize(type); 374aca59af6SIgor Mitsyanko 3758438a135SAndreas Färber g_assert_cmpint(type->instance_size, >=, sizeof(Object)); 3762f28d2ffSAnthony Liguori g_assert(type->abstract == false); 3778438a135SAndreas Färber g_assert_cmpint(size, >=, type->instance_size); 3782f28d2ffSAnthony Liguori 3792f28d2ffSAnthony Liguori memset(obj, 0, type->instance_size); 3802f28d2ffSAnthony Liguori obj->class = type->class; 381764b6312SPaolo Bonzini object_ref(obj); 382b604a854SPavel Fedin obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, 383b604a854SPavel Fedin NULL, object_property_free); 3842f28d2ffSAnthony Liguori object_init_with_type(obj, type); 3858231c2ddSEduardo Habkost object_post_init_with_type(obj, type); 3862f28d2ffSAnthony Liguori } 3872f28d2ffSAnthony Liguori 388213f0c4fSAndreas Färber void object_initialize(void *data, size_t size, const char *typename) 3892f28d2ffSAnthony Liguori { 3902f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 3912f28d2ffSAnthony Liguori 3925b9237f6SAndreas Färber object_initialize_with_type(data, size, type); 3932f28d2ffSAnthony Liguori } 3942f28d2ffSAnthony Liguori 3955d9d3f47SAndreas Färber static inline bool object_property_is_child(ObjectProperty *prop) 3965d9d3f47SAndreas Färber { 3975d9d3f47SAndreas Färber return strstart(prop->type, "child<", NULL); 3985d9d3f47SAndreas Färber } 3995d9d3f47SAndreas Färber 40057c9fafeSAnthony Liguori static void object_property_del_all(Object *obj) 40157c9fafeSAnthony Liguori { 402b604a854SPavel Fedin ObjectProperty *prop; 403b604a854SPavel Fedin GHashTableIter iter; 404b604a854SPavel Fedin gpointer key, value; 405b604a854SPavel Fedin bool released; 40657c9fafeSAnthony Liguori 407b604a854SPavel Fedin do { 408b604a854SPavel Fedin released = false; 409b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 410b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) { 411b604a854SPavel Fedin prop = value; 41257c9fafeSAnthony Liguori if (prop->release) { 41357c9fafeSAnthony Liguori prop->release(obj, prop->name, prop->opaque); 414b604a854SPavel Fedin prop->release = NULL; 415b604a854SPavel Fedin released = true; 416b604a854SPavel Fedin break; 41757c9fafeSAnthony Liguori } 418b604a854SPavel Fedin g_hash_table_iter_remove(&iter); 419b604a854SPavel Fedin } 420b604a854SPavel Fedin } while (released); 42157c9fafeSAnthony Liguori 422b604a854SPavel Fedin g_hash_table_unref(obj->properties); 42357c9fafeSAnthony Liguori } 42457c9fafeSAnthony Liguori 42557c9fafeSAnthony Liguori static void object_property_del_child(Object *obj, Object *child, Error **errp) 42657c9fafeSAnthony Liguori { 42757c9fafeSAnthony Liguori ObjectProperty *prop; 428b604a854SPavel Fedin GHashTableIter iter; 429b604a854SPavel Fedin gpointer key, value; 43057c9fafeSAnthony Liguori 431b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 432b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) { 433b604a854SPavel Fedin prop = value; 4345d9d3f47SAndreas Färber if (object_property_is_child(prop) && prop->opaque == child) { 435b604a854SPavel Fedin if (prop->release) { 436b604a854SPavel Fedin prop->release(obj, prop->name, prop->opaque); 437b604a854SPavel Fedin prop->release = NULL; 438b604a854SPavel Fedin } 439b604a854SPavel Fedin break; 440b604a854SPavel Fedin } 441b604a854SPavel Fedin } 442b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 443b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) { 444b604a854SPavel Fedin prop = value; 445b604a854SPavel Fedin if (object_property_is_child(prop) && prop->opaque == child) { 446b604a854SPavel Fedin g_hash_table_iter_remove(&iter); 4476c1fdcf9SPaolo Bonzini break; 44857c9fafeSAnthony Liguori } 44957c9fafeSAnthony Liguori } 45057c9fafeSAnthony Liguori } 45157c9fafeSAnthony Liguori 45257c9fafeSAnthony Liguori void object_unparent(Object *obj) 45357c9fafeSAnthony Liguori { 454e998fa8dSMichael S. Tsirkin if (obj->parent) { 455e998fa8dSMichael S. Tsirkin object_property_del_child(obj->parent, obj, NULL); 456e998fa8dSMichael S. Tsirkin } 45757c9fafeSAnthony Liguori } 45857c9fafeSAnthony Liguori 4592f28d2ffSAnthony Liguori static void object_deinit(Object *obj, TypeImpl *type) 4602f28d2ffSAnthony Liguori { 4612f28d2ffSAnthony Liguori if (type->instance_finalize) { 4622f28d2ffSAnthony Liguori type->instance_finalize(obj); 4632f28d2ffSAnthony Liguori } 4642f28d2ffSAnthony Liguori 4652f28d2ffSAnthony Liguori if (type_has_parent(type)) { 4662f28d2ffSAnthony Liguori object_deinit(obj, type_get_parent(type)); 4672f28d2ffSAnthony Liguori } 4682f28d2ffSAnthony Liguori } 4692f28d2ffSAnthony Liguori 470339c2708SPaolo Bonzini static void object_finalize(void *data) 4712f28d2ffSAnthony Liguori { 4722f28d2ffSAnthony Liguori Object *obj = data; 4732f28d2ffSAnthony Liguori TypeImpl *ti = obj->class->type; 4742f28d2ffSAnthony Liguori 47557c9fafeSAnthony Liguori object_property_del_all(obj); 47676a6e1ccSPaolo Bonzini object_deinit(obj, ti); 477db85b575SAnthony Liguori 4788438a135SAndreas Färber g_assert_cmpint(obj->ref, ==, 0); 479fde9bf44SPaolo Bonzini if (obj->free) { 480fde9bf44SPaolo Bonzini obj->free(obj); 481fde9bf44SPaolo Bonzini } 4822f28d2ffSAnthony Liguori } 4832f28d2ffSAnthony Liguori 48463f7b10bSMarc-André Lureau static Object *object_new_with_type(Type type) 4852f28d2ffSAnthony Liguori { 4862f28d2ffSAnthony Liguori Object *obj; 4872f28d2ffSAnthony Liguori 4882f28d2ffSAnthony Liguori g_assert(type != NULL); 489ac451033SIgor Mitsyanko type_initialize(type); 4902f28d2ffSAnthony Liguori 4912f28d2ffSAnthony Liguori obj = g_malloc(type->instance_size); 4925b9237f6SAndreas Färber object_initialize_with_type(obj, type->instance_size, type); 493fde9bf44SPaolo Bonzini obj->free = g_free; 4942f28d2ffSAnthony Liguori 4952f28d2ffSAnthony Liguori return obj; 4962f28d2ffSAnthony Liguori } 4972f28d2ffSAnthony Liguori 4982f28d2ffSAnthony Liguori Object *object_new(const char *typename) 4992f28d2ffSAnthony Liguori { 5002f28d2ffSAnthony Liguori TypeImpl *ti = type_get_by_name(typename); 5012f28d2ffSAnthony Liguori 5022f28d2ffSAnthony Liguori return object_new_with_type(ti); 5032f28d2ffSAnthony Liguori } 5042f28d2ffSAnthony Liguori 505a31bdae5SDaniel P. Berrange 506a31bdae5SDaniel P. Berrange Object *object_new_with_props(const char *typename, 507a31bdae5SDaniel P. Berrange Object *parent, 508a31bdae5SDaniel P. Berrange const char *id, 509a31bdae5SDaniel P. Berrange Error **errp, 510a31bdae5SDaniel P. Berrange ...) 511a31bdae5SDaniel P. Berrange { 512a31bdae5SDaniel P. Berrange va_list vargs; 513a31bdae5SDaniel P. Berrange Object *obj; 514a31bdae5SDaniel P. Berrange 515a31bdae5SDaniel P. Berrange va_start(vargs, errp); 516a31bdae5SDaniel P. Berrange obj = object_new_with_propv(typename, parent, id, errp, vargs); 517a31bdae5SDaniel P. Berrange va_end(vargs); 518a31bdae5SDaniel P. Berrange 519a31bdae5SDaniel P. Berrange return obj; 520a31bdae5SDaniel P. Berrange } 521a31bdae5SDaniel P. Berrange 522a31bdae5SDaniel P. Berrange 523a31bdae5SDaniel P. Berrange Object *object_new_with_propv(const char *typename, 524a31bdae5SDaniel P. Berrange Object *parent, 525a31bdae5SDaniel P. Berrange const char *id, 526a31bdae5SDaniel P. Berrange Error **errp, 527a31bdae5SDaniel P. Berrange va_list vargs) 528a31bdae5SDaniel P. Berrange { 529a31bdae5SDaniel P. Berrange Object *obj; 530a31bdae5SDaniel P. Berrange ObjectClass *klass; 531a31bdae5SDaniel P. Berrange Error *local_err = NULL; 532a31bdae5SDaniel P. Berrange 533a31bdae5SDaniel P. Berrange klass = object_class_by_name(typename); 534a31bdae5SDaniel P. Berrange if (!klass) { 535a31bdae5SDaniel P. Berrange error_setg(errp, "invalid object type: %s", typename); 536a31bdae5SDaniel P. Berrange return NULL; 537a31bdae5SDaniel P. Berrange } 538a31bdae5SDaniel P. Berrange 539a31bdae5SDaniel P. Berrange if (object_class_is_abstract(klass)) { 540a31bdae5SDaniel P. Berrange error_setg(errp, "object type '%s' is abstract", typename); 541a31bdae5SDaniel P. Berrange return NULL; 542a31bdae5SDaniel P. Berrange } 543a31bdae5SDaniel P. Berrange obj = object_new(typename); 544a31bdae5SDaniel P. Berrange 545a31bdae5SDaniel P. Berrange if (object_set_propv(obj, &local_err, vargs) < 0) { 546a31bdae5SDaniel P. Berrange goto error; 547a31bdae5SDaniel P. Berrange } 548a31bdae5SDaniel P. Berrange 549a31bdae5SDaniel P. Berrange object_property_add_child(parent, id, obj, &local_err); 550a31bdae5SDaniel P. Berrange if (local_err) { 551a31bdae5SDaniel P. Berrange goto error; 552a31bdae5SDaniel P. Berrange } 553a31bdae5SDaniel P. Berrange 554a31bdae5SDaniel P. Berrange if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { 555a31bdae5SDaniel P. Berrange user_creatable_complete(obj, &local_err); 556a31bdae5SDaniel P. Berrange if (local_err) { 557a31bdae5SDaniel P. Berrange object_unparent(obj); 558a31bdae5SDaniel P. Berrange goto error; 559a31bdae5SDaniel P. Berrange } 560a31bdae5SDaniel P. Berrange } 561a31bdae5SDaniel P. Berrange 562a31bdae5SDaniel P. Berrange object_unref(OBJECT(obj)); 563a31bdae5SDaniel P. Berrange return obj; 564a31bdae5SDaniel P. Berrange 565a31bdae5SDaniel P. Berrange error: 566a31bdae5SDaniel P. Berrange error_propagate(errp, local_err); 567a31bdae5SDaniel P. Berrange object_unref(obj); 568a31bdae5SDaniel P. Berrange return NULL; 569a31bdae5SDaniel P. Berrange } 570a31bdae5SDaniel P. Berrange 571a31bdae5SDaniel P. Berrange 572a31bdae5SDaniel P. Berrange int object_set_props(Object *obj, 573a31bdae5SDaniel P. Berrange Error **errp, 574a31bdae5SDaniel P. Berrange ...) 575a31bdae5SDaniel P. Berrange { 576a31bdae5SDaniel P. Berrange va_list vargs; 577a31bdae5SDaniel P. Berrange int ret; 578a31bdae5SDaniel P. Berrange 579a31bdae5SDaniel P. Berrange va_start(vargs, errp); 580a31bdae5SDaniel P. Berrange ret = object_set_propv(obj, errp, vargs); 581a31bdae5SDaniel P. Berrange va_end(vargs); 582a31bdae5SDaniel P. Berrange 583a31bdae5SDaniel P. Berrange return ret; 584a31bdae5SDaniel P. Berrange } 585a31bdae5SDaniel P. Berrange 586a31bdae5SDaniel P. Berrange 587a31bdae5SDaniel P. Berrange int object_set_propv(Object *obj, 588a31bdae5SDaniel P. Berrange Error **errp, 589a31bdae5SDaniel P. Berrange va_list vargs) 590a31bdae5SDaniel P. Berrange { 591a31bdae5SDaniel P. Berrange const char *propname; 592a31bdae5SDaniel P. Berrange Error *local_err = NULL; 593a31bdae5SDaniel P. Berrange 594a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *); 595a31bdae5SDaniel P. Berrange while (propname != NULL) { 596a31bdae5SDaniel P. Berrange const char *value = va_arg(vargs, char *); 597a31bdae5SDaniel P. Berrange 598a31bdae5SDaniel P. Berrange g_assert(value != NULL); 599a31bdae5SDaniel P. Berrange object_property_parse(obj, value, propname, &local_err); 600a31bdae5SDaniel P. Berrange if (local_err) { 601a31bdae5SDaniel P. Berrange error_propagate(errp, local_err); 602a31bdae5SDaniel P. Berrange return -1; 603a31bdae5SDaniel P. Berrange } 604a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *); 605a31bdae5SDaniel P. Berrange } 606a31bdae5SDaniel P. Berrange 607a31bdae5SDaniel P. Berrange return 0; 608a31bdae5SDaniel P. Berrange } 609a31bdae5SDaniel P. Berrange 610a31bdae5SDaniel P. Berrange 6112f28d2ffSAnthony Liguori Object *object_dynamic_cast(Object *obj, const char *typename) 6122f28d2ffSAnthony Liguori { 613b7f43fe4SPaolo Bonzini if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) { 614acc4af3fSPaolo Bonzini return obj; 615acc4af3fSPaolo Bonzini } 616acc4af3fSPaolo Bonzini 6172f28d2ffSAnthony Liguori return NULL; 6182f28d2ffSAnthony Liguori } 6192f28d2ffSAnthony Liguori 620be17f18bSPaolo Bonzini Object *object_dynamic_cast_assert(Object *obj, const char *typename, 621be17f18bSPaolo Bonzini const char *file, int line, const char *func) 6222f28d2ffSAnthony Liguori { 623fa131d94SPaolo Bonzini trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)", 624fa131d94SPaolo Bonzini typename, file, line, func); 625fa131d94SPaolo Bonzini 6263556c233SPaolo Bonzini #ifdef CONFIG_QOM_CAST_DEBUG 62703587328SAnthony Liguori int i; 62803587328SAnthony Liguori Object *inst; 62903587328SAnthony Liguori 63095916abcSPeter Crosthwaite for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { 631b6b3ccfdSAlex Bennée if (atomic_read(&obj->class->object_cast_cache[i]) == typename) { 63203587328SAnthony Liguori goto out; 63303587328SAnthony Liguori } 63403587328SAnthony Liguori } 63503587328SAnthony Liguori 63603587328SAnthony Liguori inst = object_dynamic_cast(obj, typename); 6372f28d2ffSAnthony Liguori 638b7f43fe4SPaolo Bonzini if (!inst && obj) { 639be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 640be17f18bSPaolo Bonzini file, line, func, obj, typename); 6412f28d2ffSAnthony Liguori abort(); 6422f28d2ffSAnthony Liguori } 6432f28d2ffSAnthony Liguori 6443556c233SPaolo Bonzini assert(obj == inst); 64503587328SAnthony Liguori 64695916abcSPeter Crosthwaite if (obj && obj == inst) { 64703587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 648b6b3ccfdSAlex Bennée atomic_set(&obj->class->object_cast_cache[i - 1], 649b6b3ccfdSAlex Bennée atomic_read(&obj->class->object_cast_cache[i])); 65003587328SAnthony Liguori } 651b6b3ccfdSAlex Bennée atomic_set(&obj->class->object_cast_cache[i - 1], typename); 65203587328SAnthony Liguori } 65303587328SAnthony Liguori 65403587328SAnthony Liguori out: 6553556c233SPaolo Bonzini #endif 6563556c233SPaolo Bonzini return obj; 6572f28d2ffSAnthony Liguori } 6582f28d2ffSAnthony Liguori 6592f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast(ObjectClass *class, 6602f28d2ffSAnthony Liguori const char *typename) 6612f28d2ffSAnthony Liguori { 66233e95c63SAnthony Liguori ObjectClass *ret = NULL; 663bf0fda34SPaolo Bonzini TypeImpl *target_type; 664bf0fda34SPaolo Bonzini TypeImpl *type; 6652f28d2ffSAnthony Liguori 666bf0fda34SPaolo Bonzini if (!class) { 667bf0fda34SPaolo Bonzini return NULL; 668bf0fda34SPaolo Bonzini } 669bf0fda34SPaolo Bonzini 670793c96b5SPaolo Bonzini /* A simple fast path that can trigger a lot for leaf classes. */ 671bf0fda34SPaolo Bonzini type = class->type; 672793c96b5SPaolo Bonzini if (type->name == typename) { 673793c96b5SPaolo Bonzini return class; 674793c96b5SPaolo Bonzini } 675793c96b5SPaolo Bonzini 676bf0fda34SPaolo Bonzini target_type = type_get_by_name(typename); 6779ab880b3SAlexander Graf if (!target_type) { 6789ab880b3SAlexander Graf /* target class type unknown, so fail the cast */ 6799ab880b3SAlexander Graf return NULL; 6809ab880b3SAlexander Graf } 6819ab880b3SAlexander Graf 68200e2ceaeSPeter Crosthwaite if (type->class->interfaces && 68300e2ceaeSPeter Crosthwaite type_is_ancestor(target_type, type_interface)) { 68433e95c63SAnthony Liguori int found = 0; 68533e95c63SAnthony Liguori GSList *i; 68633e95c63SAnthony Liguori 68733e95c63SAnthony Liguori for (i = class->interfaces; i; i = i->next) { 68833e95c63SAnthony Liguori ObjectClass *target_class = i->data; 68933e95c63SAnthony Liguori 69033e95c63SAnthony Liguori if (type_is_ancestor(target_class->type, target_type)) { 69133e95c63SAnthony Liguori ret = target_class; 69233e95c63SAnthony Liguori found++; 69333e95c63SAnthony Liguori } 6942f28d2ffSAnthony Liguori } 6952f28d2ffSAnthony Liguori 69633e95c63SAnthony Liguori /* The match was ambiguous, don't allow a cast */ 69733e95c63SAnthony Liguori if (found > 1) { 69833e95c63SAnthony Liguori ret = NULL; 69933e95c63SAnthony Liguori } 70033e95c63SAnthony Liguori } else if (type_is_ancestor(type, target_type)) { 70133e95c63SAnthony Liguori ret = class; 7022f28d2ffSAnthony Liguori } 7032f28d2ffSAnthony Liguori 70433e95c63SAnthony Liguori return ret; 7052f28d2ffSAnthony Liguori } 7062f28d2ffSAnthony Liguori 7072f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 708be17f18bSPaolo Bonzini const char *typename, 709be17f18bSPaolo Bonzini const char *file, int line, 710be17f18bSPaolo Bonzini const char *func) 7112f28d2ffSAnthony Liguori { 712fa131d94SPaolo Bonzini ObjectClass *ret; 7132f28d2ffSAnthony Liguori 714fa131d94SPaolo Bonzini trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)", 715fa131d94SPaolo Bonzini typename, file, line, func); 716fa131d94SPaolo Bonzini 71703587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG 71803587328SAnthony Liguori int i; 71903587328SAnthony Liguori 7209d6a3d58SPeter Crosthwaite for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { 721b6b3ccfdSAlex Bennée if (atomic_read(&class->class_cast_cache[i]) == typename) { 72203587328SAnthony Liguori ret = class; 72303587328SAnthony Liguori goto out; 72403587328SAnthony Liguori } 72503587328SAnthony Liguori } 72603587328SAnthony Liguori #else 7279d6a3d58SPeter Crosthwaite if (!class || !class->interfaces) { 7283556c233SPaolo Bonzini return class; 7293556c233SPaolo Bonzini } 7303556c233SPaolo Bonzini #endif 7313556c233SPaolo Bonzini 732fa131d94SPaolo Bonzini ret = object_class_dynamic_cast(class, typename); 733bf0fda34SPaolo Bonzini if (!ret && class) { 734be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 735be17f18bSPaolo Bonzini file, line, func, class, typename); 7362f28d2ffSAnthony Liguori abort(); 7372f28d2ffSAnthony Liguori } 7382f28d2ffSAnthony Liguori 73903587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG 7409d6a3d58SPeter Crosthwaite if (class && ret == class) { 74103587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 742b6b3ccfdSAlex Bennée atomic_set(&class->class_cast_cache[i - 1], 743b6b3ccfdSAlex Bennée atomic_read(&class->class_cast_cache[i])); 74403587328SAnthony Liguori } 745b6b3ccfdSAlex Bennée atomic_set(&class->class_cast_cache[i - 1], typename); 74603587328SAnthony Liguori } 74703587328SAnthony Liguori out: 74803587328SAnthony Liguori #endif 7492f28d2ffSAnthony Liguori return ret; 7502f28d2ffSAnthony Liguori } 7512f28d2ffSAnthony Liguori 7528f5d58efSIgor Mammedov const char *object_get_typename(const Object *obj) 7532f28d2ffSAnthony Liguori { 7542f28d2ffSAnthony Liguori return obj->class->type->name; 7552f28d2ffSAnthony Liguori } 7562f28d2ffSAnthony Liguori 7572f28d2ffSAnthony Liguori ObjectClass *object_get_class(Object *obj) 7582f28d2ffSAnthony Liguori { 7592f28d2ffSAnthony Liguori return obj->class; 7602f28d2ffSAnthony Liguori } 7612f28d2ffSAnthony Liguori 76217862378SAndreas Färber bool object_class_is_abstract(ObjectClass *klass) 76317862378SAndreas Färber { 76417862378SAndreas Färber return klass->type->abstract; 76517862378SAndreas Färber } 76617862378SAndreas Färber 7672f28d2ffSAnthony Liguori const char *object_class_get_name(ObjectClass *klass) 7682f28d2ffSAnthony Liguori { 7692f28d2ffSAnthony Liguori return klass->type->name; 7702f28d2ffSAnthony Liguori } 7712f28d2ffSAnthony Liguori 7722f28d2ffSAnthony Liguori ObjectClass *object_class_by_name(const char *typename) 7732f28d2ffSAnthony Liguori { 7742f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 7752f28d2ffSAnthony Liguori 7762f28d2ffSAnthony Liguori if (!type) { 7772f28d2ffSAnthony Liguori return NULL; 7782f28d2ffSAnthony Liguori } 7792f28d2ffSAnthony Liguori 780ac451033SIgor Mitsyanko type_initialize(type); 7812f28d2ffSAnthony Liguori 7822f28d2ffSAnthony Liguori return type->class; 7832f28d2ffSAnthony Liguori } 7842f28d2ffSAnthony Liguori 785e7cce67fSPaolo Bonzini ObjectClass *object_class_get_parent(ObjectClass *class) 786e7cce67fSPaolo Bonzini { 787e7cce67fSPaolo Bonzini TypeImpl *type = type_get_parent(class->type); 788e7cce67fSPaolo Bonzini 789e7cce67fSPaolo Bonzini if (!type) { 790e7cce67fSPaolo Bonzini return NULL; 791e7cce67fSPaolo Bonzini } 792e7cce67fSPaolo Bonzini 793e7cce67fSPaolo Bonzini type_initialize(type); 794e7cce67fSPaolo Bonzini 795e7cce67fSPaolo Bonzini return type->class; 796e7cce67fSPaolo Bonzini } 797e7cce67fSPaolo Bonzini 7982f28d2ffSAnthony Liguori typedef struct OCFData 7992f28d2ffSAnthony Liguori { 8002f28d2ffSAnthony Liguori void (*fn)(ObjectClass *klass, void *opaque); 80193c511a1SAnthony Liguori const char *implements_type; 80293c511a1SAnthony Liguori bool include_abstract; 8032f28d2ffSAnthony Liguori void *opaque; 8042f28d2ffSAnthony Liguori } OCFData; 8052f28d2ffSAnthony Liguori 8062f28d2ffSAnthony Liguori static void object_class_foreach_tramp(gpointer key, gpointer value, 8072f28d2ffSAnthony Liguori gpointer opaque) 8082f28d2ffSAnthony Liguori { 8092f28d2ffSAnthony Liguori OCFData *data = opaque; 8102f28d2ffSAnthony Liguori TypeImpl *type = value; 81193c511a1SAnthony Liguori ObjectClass *k; 8122f28d2ffSAnthony Liguori 813ac451033SIgor Mitsyanko type_initialize(type); 81493c511a1SAnthony Liguori k = type->class; 8152f28d2ffSAnthony Liguori 81693c511a1SAnthony Liguori if (!data->include_abstract && type->abstract) { 81793c511a1SAnthony Liguori return; 81893c511a1SAnthony Liguori } 81993c511a1SAnthony Liguori 82093c511a1SAnthony Liguori if (data->implements_type && 82193c511a1SAnthony Liguori !object_class_dynamic_cast(k, data->implements_type)) { 82293c511a1SAnthony Liguori return; 82393c511a1SAnthony Liguori } 82493c511a1SAnthony Liguori 82593c511a1SAnthony Liguori data->fn(k, data->opaque); 8262f28d2ffSAnthony Liguori } 8272f28d2ffSAnthony Liguori 8282f28d2ffSAnthony Liguori void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 82993c511a1SAnthony Liguori const char *implements_type, bool include_abstract, 8302f28d2ffSAnthony Liguori void *opaque) 8312f28d2ffSAnthony Liguori { 83293c511a1SAnthony Liguori OCFData data = { fn, implements_type, include_abstract, opaque }; 8332f28d2ffSAnthony Liguori 834f54c19caSHervé Poussineau enumerating_types = true; 8352f28d2ffSAnthony Liguori g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 836f54c19caSHervé Poussineau enumerating_types = false; 8372f28d2ffSAnthony Liguori } 83857c9fafeSAnthony Liguori 839d714b8deSPeter Crosthwaite static int do_object_child_foreach(Object *obj, 840d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque), 841d714b8deSPeter Crosthwaite void *opaque, bool recurse) 84232efc535SPaolo Bonzini { 843b604a854SPavel Fedin GHashTableIter iter; 844b604a854SPavel Fedin ObjectProperty *prop; 84532efc535SPaolo Bonzini int ret = 0; 84632efc535SPaolo Bonzini 847b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 848b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 84932efc535SPaolo Bonzini if (object_property_is_child(prop)) { 850d714b8deSPeter Crosthwaite Object *child = prop->opaque; 851d714b8deSPeter Crosthwaite 852d714b8deSPeter Crosthwaite ret = fn(child, opaque); 85332efc535SPaolo Bonzini if (ret != 0) { 85432efc535SPaolo Bonzini break; 85532efc535SPaolo Bonzini } 856d714b8deSPeter Crosthwaite if (recurse) { 857d714b8deSPeter Crosthwaite do_object_child_foreach(child, fn, opaque, true); 858d714b8deSPeter Crosthwaite } 85932efc535SPaolo Bonzini } 86032efc535SPaolo Bonzini } 86132efc535SPaolo Bonzini return ret; 86232efc535SPaolo Bonzini } 86332efc535SPaolo Bonzini 864d714b8deSPeter Crosthwaite int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), 865d714b8deSPeter Crosthwaite void *opaque) 866d714b8deSPeter Crosthwaite { 867d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, false); 868d714b8deSPeter Crosthwaite } 869d714b8deSPeter Crosthwaite 870d714b8deSPeter Crosthwaite int object_child_foreach_recursive(Object *obj, 871d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque), 872d714b8deSPeter Crosthwaite void *opaque) 873d714b8deSPeter Crosthwaite { 874d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, true); 875d714b8deSPeter Crosthwaite } 876d714b8deSPeter Crosthwaite 877418ba9e5SAndreas Färber static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) 878418ba9e5SAndreas Färber { 879418ba9e5SAndreas Färber GSList **list = opaque; 880418ba9e5SAndreas Färber 881418ba9e5SAndreas Färber *list = g_slist_prepend(*list, klass); 882418ba9e5SAndreas Färber } 883418ba9e5SAndreas Färber 884418ba9e5SAndreas Färber GSList *object_class_get_list(const char *implements_type, 885418ba9e5SAndreas Färber bool include_abstract) 886418ba9e5SAndreas Färber { 887418ba9e5SAndreas Färber GSList *list = NULL; 888418ba9e5SAndreas Färber 889418ba9e5SAndreas Färber object_class_foreach(object_class_get_list_tramp, 890418ba9e5SAndreas Färber implements_type, include_abstract, &list); 891418ba9e5SAndreas Färber return list; 892418ba9e5SAndreas Färber } 893418ba9e5SAndreas Färber 89447c66009SPaolo Bonzini static gint object_class_cmp(gconstpointer a, gconstpointer b) 89547c66009SPaolo Bonzini { 89647c66009SPaolo Bonzini return strcasecmp(object_class_get_name((ObjectClass *)a), 89747c66009SPaolo Bonzini object_class_get_name((ObjectClass *)b)); 89847c66009SPaolo Bonzini } 89947c66009SPaolo Bonzini 90047c66009SPaolo Bonzini GSList *object_class_get_list_sorted(const char *implements_type, 90147c66009SPaolo Bonzini bool include_abstract) 90247c66009SPaolo Bonzini { 90347c66009SPaolo Bonzini return g_slist_sort(object_class_get_list(implements_type, include_abstract), 90447c66009SPaolo Bonzini object_class_cmp); 90547c66009SPaolo Bonzini } 90647c66009SPaolo Bonzini 90757c9fafeSAnthony Liguori void object_ref(Object *obj) 90857c9fafeSAnthony Liguori { 9098ffad850SPeter Crosthwaite if (!obj) { 9108ffad850SPeter Crosthwaite return; 9118ffad850SPeter Crosthwaite } 912f08c03f3SJan Kiszka atomic_inc(&obj->ref); 91357c9fafeSAnthony Liguori } 91457c9fafeSAnthony Liguori 91557c9fafeSAnthony Liguori void object_unref(Object *obj) 91657c9fafeSAnthony Liguori { 9178ffad850SPeter Crosthwaite if (!obj) { 9188ffad850SPeter Crosthwaite return; 9198ffad850SPeter Crosthwaite } 9208438a135SAndreas Färber g_assert_cmpint(obj->ref, >, 0); 92157c9fafeSAnthony Liguori 92257c9fafeSAnthony Liguori /* parent always holds a reference to its children */ 923f08c03f3SJan Kiszka if (atomic_fetch_dec(&obj->ref) == 1) { 92457c9fafeSAnthony Liguori object_finalize(obj); 92557c9fafeSAnthony Liguori } 92657c9fafeSAnthony Liguori } 92757c9fafeSAnthony Liguori 92864607d08SPaolo Bonzini ObjectProperty * 92964607d08SPaolo Bonzini object_property_add(Object *obj, const char *name, const char *type, 93057c9fafeSAnthony Liguori ObjectPropertyAccessor *get, 93157c9fafeSAnthony Liguori ObjectPropertyAccessor *set, 93257c9fafeSAnthony Liguori ObjectPropertyRelease *release, 93357c9fafeSAnthony Liguori void *opaque, Error **errp) 93457c9fafeSAnthony Liguori { 93554852b03SPeter Maydell ObjectProperty *prop; 93633965904SPeter Crosthwaite size_t name_len = strlen(name); 93733965904SPeter Crosthwaite 93833965904SPeter Crosthwaite if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { 93933965904SPeter Crosthwaite int i; 94033965904SPeter Crosthwaite ObjectProperty *ret; 94133965904SPeter Crosthwaite char *name_no_array = g_strdup(name); 94233965904SPeter Crosthwaite 94333965904SPeter Crosthwaite name_no_array[name_len - 3] = '\0'; 94433965904SPeter Crosthwaite for (i = 0; ; ++i) { 94533965904SPeter Crosthwaite char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); 94633965904SPeter Crosthwaite 94733965904SPeter Crosthwaite ret = object_property_add(obj, full_name, type, get, set, 94833965904SPeter Crosthwaite release, opaque, NULL); 94933965904SPeter Crosthwaite g_free(full_name); 95033965904SPeter Crosthwaite if (ret) { 95133965904SPeter Crosthwaite break; 95233965904SPeter Crosthwaite } 95333965904SPeter Crosthwaite } 95433965904SPeter Crosthwaite g_free(name_no_array); 95533965904SPeter Crosthwaite return ret; 95633965904SPeter Crosthwaite } 95754852b03SPeter Maydell 95816bf7f52SDaniel P. Berrange if (object_property_find(obj, name, NULL) != NULL) { 95954852b03SPeter Maydell error_setg(errp, "attempt to add duplicate property '%s'" 96054852b03SPeter Maydell " to object (type '%s')", name, 96154852b03SPeter Maydell object_get_typename(obj)); 96264607d08SPaolo Bonzini return NULL; 96354852b03SPeter Maydell } 96454852b03SPeter Maydell 96554852b03SPeter Maydell prop = g_malloc0(sizeof(*prop)); 96657c9fafeSAnthony Liguori 96757c9fafeSAnthony Liguori prop->name = g_strdup(name); 96857c9fafeSAnthony Liguori prop->type = g_strdup(type); 96957c9fafeSAnthony Liguori 97057c9fafeSAnthony Liguori prop->get = get; 97157c9fafeSAnthony Liguori prop->set = set; 97257c9fafeSAnthony Liguori prop->release = release; 97357c9fafeSAnthony Liguori prop->opaque = opaque; 97457c9fafeSAnthony Liguori 975b604a854SPavel Fedin g_hash_table_insert(obj->properties, prop->name, prop); 97664607d08SPaolo Bonzini return prop; 97757c9fafeSAnthony Liguori } 97857c9fafeSAnthony Liguori 97916bf7f52SDaniel P. Berrange ObjectProperty * 98016bf7f52SDaniel P. Berrange object_class_property_add(ObjectClass *klass, 98116bf7f52SDaniel P. Berrange const char *name, 98216bf7f52SDaniel P. Berrange const char *type, 98316bf7f52SDaniel P. Berrange ObjectPropertyAccessor *get, 98416bf7f52SDaniel P. Berrange ObjectPropertyAccessor *set, 98516bf7f52SDaniel P. Berrange ObjectPropertyRelease *release, 98616bf7f52SDaniel P. Berrange void *opaque, 98716bf7f52SDaniel P. Berrange Error **errp) 98816bf7f52SDaniel P. Berrange { 98916bf7f52SDaniel P. Berrange ObjectProperty *prop; 99016bf7f52SDaniel P. Berrange 99116bf7f52SDaniel P. Berrange if (object_class_property_find(klass, name, NULL) != NULL) { 99216bf7f52SDaniel P. Berrange error_setg(errp, "attempt to add duplicate property '%s'" 99316bf7f52SDaniel P. Berrange " to object (type '%s')", name, 99416bf7f52SDaniel P. Berrange object_class_get_name(klass)); 99516bf7f52SDaniel P. Berrange return NULL; 99616bf7f52SDaniel P. Berrange } 99716bf7f52SDaniel P. Berrange 99816bf7f52SDaniel P. Berrange prop = g_malloc0(sizeof(*prop)); 99916bf7f52SDaniel P. Berrange 100016bf7f52SDaniel P. Berrange prop->name = g_strdup(name); 100116bf7f52SDaniel P. Berrange prop->type = g_strdup(type); 100216bf7f52SDaniel P. Berrange 100316bf7f52SDaniel P. Berrange prop->get = get; 100416bf7f52SDaniel P. Berrange prop->set = set; 100516bf7f52SDaniel P. Berrange prop->release = release; 100616bf7f52SDaniel P. Berrange prop->opaque = opaque; 100716bf7f52SDaniel P. Berrange 100816bf7f52SDaniel P. Berrange g_hash_table_insert(klass->properties, g_strdup(name), prop); 100916bf7f52SDaniel P. Berrange 101016bf7f52SDaniel P. Berrange return prop; 101116bf7f52SDaniel P. Berrange } 101216bf7f52SDaniel P. Berrange 101389bfe000SPaolo Bonzini ObjectProperty *object_property_find(Object *obj, const char *name, 101489bfe000SPaolo Bonzini Error **errp) 101557c9fafeSAnthony Liguori { 101657c9fafeSAnthony Liguori ObjectProperty *prop; 101716bf7f52SDaniel P. Berrange ObjectClass *klass = object_get_class(obj); 101816bf7f52SDaniel P. Berrange 101916bf7f52SDaniel P. Berrange prop = object_class_property_find(klass, name, NULL); 102016bf7f52SDaniel P. Berrange if (prop) { 102116bf7f52SDaniel P. Berrange return prop; 102216bf7f52SDaniel P. Berrange } 102357c9fafeSAnthony Liguori 1024b604a854SPavel Fedin prop = g_hash_table_lookup(obj->properties, name); 1025b604a854SPavel Fedin if (prop) { 102657c9fafeSAnthony Liguori return prop; 102757c9fafeSAnthony Liguori } 102857c9fafeSAnthony Liguori 1029f231b88dSCole Robinson error_setg(errp, "Property '.%s' not found", name); 103057c9fafeSAnthony Liguori return NULL; 103157c9fafeSAnthony Liguori } 103257c9fafeSAnthony Liguori 10337746abd8SDaniel P. Berrange void object_property_iter_init(ObjectPropertyIterator *iter, 10347746abd8SDaniel P. Berrange Object *obj) 1035a00c9482SDaniel P. Berrange { 10367746abd8SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, obj->properties); 10377746abd8SDaniel P. Berrange iter->nextclass = object_get_class(obj); 1038a00c9482SDaniel P. Berrange } 1039a00c9482SDaniel P. Berrange 1040a00c9482SDaniel P. Berrange ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) 1041a00c9482SDaniel P. Berrange { 1042b604a854SPavel Fedin gpointer key, val; 104316bf7f52SDaniel P. Berrange while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { 104416bf7f52SDaniel P. Berrange if (!iter->nextclass) { 1045b604a854SPavel Fedin return NULL; 1046a00c9482SDaniel P. Berrange } 104716bf7f52SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, iter->nextclass->properties); 104816bf7f52SDaniel P. Berrange iter->nextclass = object_class_get_parent(iter->nextclass); 104916bf7f52SDaniel P. Berrange } 1050b604a854SPavel Fedin return val; 1051a00c9482SDaniel P. Berrange } 1052a00c9482SDaniel P. Berrange 1053961c47bbSAlexey Kardashevskiy void object_class_property_iter_init(ObjectPropertyIterator *iter, 1054961c47bbSAlexey Kardashevskiy ObjectClass *klass) 1055961c47bbSAlexey Kardashevskiy { 1056961c47bbSAlexey Kardashevskiy g_hash_table_iter_init(&iter->iter, klass->properties); 1057961c47bbSAlexey Kardashevskiy iter->nextclass = klass; 1058961c47bbSAlexey Kardashevskiy } 1059961c47bbSAlexey Kardashevskiy 106016bf7f52SDaniel P. Berrange ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, 106116bf7f52SDaniel P. Berrange Error **errp) 106216bf7f52SDaniel P. Berrange { 106316bf7f52SDaniel P. Berrange ObjectProperty *prop; 106416bf7f52SDaniel P. Berrange ObjectClass *parent_klass; 106516bf7f52SDaniel P. Berrange 106616bf7f52SDaniel P. Berrange parent_klass = object_class_get_parent(klass); 106716bf7f52SDaniel P. Berrange if (parent_klass) { 106816bf7f52SDaniel P. Berrange prop = object_class_property_find(parent_klass, name, NULL); 106916bf7f52SDaniel P. Berrange if (prop) { 107016bf7f52SDaniel P. Berrange return prop; 107116bf7f52SDaniel P. Berrange } 107216bf7f52SDaniel P. Berrange } 107316bf7f52SDaniel P. Berrange 107416bf7f52SDaniel P. Berrange prop = g_hash_table_lookup(klass->properties, name); 107516bf7f52SDaniel P. Berrange if (!prop) { 107616bf7f52SDaniel P. Berrange error_setg(errp, "Property '.%s' not found", name); 107716bf7f52SDaniel P. Berrange } 107816bf7f52SDaniel P. Berrange return prop; 107916bf7f52SDaniel P. Berrange } 108016bf7f52SDaniel P. Berrange 108157c9fafeSAnthony Liguori void object_property_del(Object *obj, const char *name, Error **errp) 108257c9fafeSAnthony Liguori { 1083b604a854SPavel Fedin ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); 1084b604a854SPavel Fedin 1085b604a854SPavel Fedin if (!prop) { 1086b604a854SPavel Fedin error_setg(errp, "Property '.%s' not found", name); 10870866aca1SAnthony Liguori return; 10880866aca1SAnthony Liguori } 108957c9fafeSAnthony Liguori 10900866aca1SAnthony Liguori if (prop->release) { 10910866aca1SAnthony Liguori prop->release(obj, name, prop->opaque); 10920866aca1SAnthony Liguori } 1093b604a854SPavel Fedin g_hash_table_remove(obj->properties, name); 109457c9fafeSAnthony Liguori } 109557c9fafeSAnthony Liguori 109657c9fafeSAnthony Liguori void object_property_get(Object *obj, Visitor *v, const char *name, 109757c9fafeSAnthony Liguori Error **errp) 109857c9fafeSAnthony Liguori { 109989bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 110057c9fafeSAnthony Liguori if (prop == NULL) { 110157c9fafeSAnthony Liguori return; 110257c9fafeSAnthony Liguori } 110357c9fafeSAnthony Liguori 110457c9fafeSAnthony Liguori if (!prop->get) { 1105c6bd8c70SMarkus Armbruster error_setg(errp, QERR_PERMISSION_DENIED); 110657c9fafeSAnthony Liguori } else { 1107d7bce999SEric Blake prop->get(obj, v, name, prop->opaque, errp); 110857c9fafeSAnthony Liguori } 110957c9fafeSAnthony Liguori } 111057c9fafeSAnthony Liguori 111157c9fafeSAnthony Liguori void object_property_set(Object *obj, Visitor *v, const char *name, 111257c9fafeSAnthony Liguori Error **errp) 111357c9fafeSAnthony Liguori { 111489bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 111557c9fafeSAnthony Liguori if (prop == NULL) { 111657c9fafeSAnthony Liguori return; 111757c9fafeSAnthony Liguori } 111857c9fafeSAnthony Liguori 111957c9fafeSAnthony Liguori if (!prop->set) { 1120c6bd8c70SMarkus Armbruster error_setg(errp, QERR_PERMISSION_DENIED); 112157c9fafeSAnthony Liguori } else { 1122d7bce999SEric Blake prop->set(obj, v, name, prop->opaque, errp); 112357c9fafeSAnthony Liguori } 112457c9fafeSAnthony Liguori } 112557c9fafeSAnthony Liguori 11267b7b7d18SPaolo Bonzini void object_property_set_str(Object *obj, const char *value, 11277b7b7d18SPaolo Bonzini const char *name, Error **errp) 11287b7b7d18SPaolo Bonzini { 11297b7b7d18SPaolo Bonzini QString *qstr = qstring_from_str(value); 11307b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qstr), name, errp); 11317b7b7d18SPaolo Bonzini 11327b7b7d18SPaolo Bonzini QDECREF(qstr); 11337b7b7d18SPaolo Bonzini } 11347b7b7d18SPaolo Bonzini 11357b7b7d18SPaolo Bonzini char *object_property_get_str(Object *obj, const char *name, 11367b7b7d18SPaolo Bonzini Error **errp) 11377b7b7d18SPaolo Bonzini { 11387b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 11397b7b7d18SPaolo Bonzini char *retval; 11407b7b7d18SPaolo Bonzini 11417b7b7d18SPaolo Bonzini if (!ret) { 11427b7b7d18SPaolo Bonzini return NULL; 11437b7b7d18SPaolo Bonzini } 1144*aafb21a0SPeter Xu 1145*aafb21a0SPeter Xu retval = g_strdup(qobject_get_try_str(ret)); 1146*aafb21a0SPeter Xu if (!retval) { 1147c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); 11487b7b7d18SPaolo Bonzini } 11497b7b7d18SPaolo Bonzini 1150560f19f1SMarc-André Lureau qobject_decref(ret); 11517b7b7d18SPaolo Bonzini return retval; 11527b7b7d18SPaolo Bonzini } 11537b7b7d18SPaolo Bonzini 11541d9c5a12SPaolo Bonzini void object_property_set_link(Object *obj, Object *value, 11551d9c5a12SPaolo Bonzini const char *name, Error **errp) 11561d9c5a12SPaolo Bonzini { 1157d3c49316SPeter Crosthwaite if (value) { 11582d3aa28cSVlad Yasevich gchar *path = object_get_canonical_path(value); 11592d3aa28cSVlad Yasevich object_property_set_str(obj, path, name, errp); 11602d3aa28cSVlad Yasevich g_free(path); 1161d3c49316SPeter Crosthwaite } else { 1162d3c49316SPeter Crosthwaite object_property_set_str(obj, "", name, errp); 1163d3c49316SPeter Crosthwaite } 11641d9c5a12SPaolo Bonzini } 11651d9c5a12SPaolo Bonzini 11661d9c5a12SPaolo Bonzini Object *object_property_get_link(Object *obj, const char *name, 11671d9c5a12SPaolo Bonzini Error **errp) 11681d9c5a12SPaolo Bonzini { 11691d9c5a12SPaolo Bonzini char *str = object_property_get_str(obj, name, errp); 11701d9c5a12SPaolo Bonzini Object *target = NULL; 11711d9c5a12SPaolo Bonzini 11721d9c5a12SPaolo Bonzini if (str && *str) { 11731d9c5a12SPaolo Bonzini target = object_resolve_path(str, NULL); 11741d9c5a12SPaolo Bonzini if (!target) { 117575158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 117675158ebbSMarkus Armbruster "Device '%s' not found", str); 11771d9c5a12SPaolo Bonzini } 11781d9c5a12SPaolo Bonzini } 11791d9c5a12SPaolo Bonzini 11801d9c5a12SPaolo Bonzini g_free(str); 11811d9c5a12SPaolo Bonzini return target; 11821d9c5a12SPaolo Bonzini } 11831d9c5a12SPaolo Bonzini 11847b7b7d18SPaolo Bonzini void object_property_set_bool(Object *obj, bool value, 11857b7b7d18SPaolo Bonzini const char *name, Error **errp) 11867b7b7d18SPaolo Bonzini { 1187fc48ffc3SEric Blake QBool *qbool = qbool_from_bool(value); 11887b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qbool), name, errp); 11897b7b7d18SPaolo Bonzini 11907b7b7d18SPaolo Bonzini QDECREF(qbool); 11917b7b7d18SPaolo Bonzini } 11927b7b7d18SPaolo Bonzini 11937b7b7d18SPaolo Bonzini bool object_property_get_bool(Object *obj, const char *name, 11947b7b7d18SPaolo Bonzini Error **errp) 11957b7b7d18SPaolo Bonzini { 11967b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 11977b7b7d18SPaolo Bonzini QBool *qbool; 11987b7b7d18SPaolo Bonzini bool retval; 11997b7b7d18SPaolo Bonzini 12007b7b7d18SPaolo Bonzini if (!ret) { 12017b7b7d18SPaolo Bonzini return false; 12027b7b7d18SPaolo Bonzini } 12037dc847ebSMax Reitz qbool = qobject_to(QBool, ret); 12047b7b7d18SPaolo Bonzini if (!qbool) { 1205c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); 12067b7b7d18SPaolo Bonzini retval = false; 12077b7b7d18SPaolo Bonzini } else { 1208fc48ffc3SEric Blake retval = qbool_get_bool(qbool); 12097b7b7d18SPaolo Bonzini } 12107b7b7d18SPaolo Bonzini 1211560f19f1SMarc-André Lureau qobject_decref(ret); 12127b7b7d18SPaolo Bonzini return retval; 12137b7b7d18SPaolo Bonzini } 12147b7b7d18SPaolo Bonzini 12157b7b7d18SPaolo Bonzini void object_property_set_int(Object *obj, int64_t value, 12167b7b7d18SPaolo Bonzini const char *name, Error **errp) 12177b7b7d18SPaolo Bonzini { 121801b2ffceSMarc-André Lureau QNum *qnum = qnum_from_int(value); 121901b2ffceSMarc-André Lureau object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 12207b7b7d18SPaolo Bonzini 122101b2ffceSMarc-André Lureau QDECREF(qnum); 12227b7b7d18SPaolo Bonzini } 12237b7b7d18SPaolo Bonzini 12247b7b7d18SPaolo Bonzini int64_t object_property_get_int(Object *obj, const char *name, 12257b7b7d18SPaolo Bonzini Error **errp) 12267b7b7d18SPaolo Bonzini { 12277b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 122801b2ffceSMarc-André Lureau QNum *qnum; 12297b7b7d18SPaolo Bonzini int64_t retval; 12307b7b7d18SPaolo Bonzini 12317b7b7d18SPaolo Bonzini if (!ret) { 12327b7b7d18SPaolo Bonzini return -1; 12337b7b7d18SPaolo Bonzini } 123401b2ffceSMarc-André Lureau 12357dc847ebSMax Reitz qnum = qobject_to(QNum, ret); 123601b2ffceSMarc-André Lureau if (!qnum || !qnum_get_try_int(qnum, &retval)) { 1237c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); 12387b7b7d18SPaolo Bonzini retval = -1; 12397b7b7d18SPaolo Bonzini } 12407b7b7d18SPaolo Bonzini 1241560f19f1SMarc-André Lureau qobject_decref(ret); 12427b7b7d18SPaolo Bonzini return retval; 12437b7b7d18SPaolo Bonzini } 12447b7b7d18SPaolo Bonzini 12453152779cSMarc-André Lureau void object_property_set_uint(Object *obj, uint64_t value, 12463152779cSMarc-André Lureau const char *name, Error **errp) 12473152779cSMarc-André Lureau { 12483152779cSMarc-André Lureau QNum *qnum = qnum_from_uint(value); 12493152779cSMarc-André Lureau 12503152779cSMarc-André Lureau object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 12513152779cSMarc-André Lureau QDECREF(qnum); 12523152779cSMarc-André Lureau } 12533152779cSMarc-André Lureau 12543152779cSMarc-André Lureau uint64_t object_property_get_uint(Object *obj, const char *name, 12553152779cSMarc-André Lureau Error **errp) 12563152779cSMarc-André Lureau { 12573152779cSMarc-André Lureau QObject *ret = object_property_get_qobject(obj, name, errp); 12583152779cSMarc-André Lureau QNum *qnum; 12593152779cSMarc-André Lureau uint64_t retval; 12603152779cSMarc-André Lureau 12613152779cSMarc-André Lureau if (!ret) { 12623152779cSMarc-André Lureau return 0; 12633152779cSMarc-André Lureau } 12647dc847ebSMax Reitz qnum = qobject_to(QNum, ret); 12653152779cSMarc-André Lureau if (!qnum || !qnum_get_try_uint(qnum, &retval)) { 12663152779cSMarc-André Lureau error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint"); 12673152779cSMarc-André Lureau retval = 0; 12683152779cSMarc-André Lureau } 12693152779cSMarc-André Lureau 12703152779cSMarc-André Lureau qobject_decref(ret); 12713152779cSMarc-André Lureau return retval; 12723152779cSMarc-André Lureau } 12733152779cSMarc-André Lureau 1274a8e3fbedSDaniel P. Berrange typedef struct EnumProperty { 1275f7abe0ecSMarc-André Lureau const QEnumLookup *lookup; 1276a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **); 1277a8e3fbedSDaniel P. Berrange void (*set)(Object *, int, Error **); 1278a8e3fbedSDaniel P. Berrange } EnumProperty; 1279a8e3fbedSDaniel P. Berrange 12801f21772dSHu Tao int object_property_get_enum(Object *obj, const char *name, 1281a3590dacSDaniel P. Berrange const char *typename, Error **errp) 12821f21772dSHu Tao { 12834715d42eSMarkus Armbruster Error *err = NULL; 12847a0525c7SEric Blake Visitor *v; 1285976620acSChen Fan char *str; 12861f21772dSHu Tao int ret; 1287a3590dacSDaniel P. Berrange ObjectProperty *prop = object_property_find(obj, name, errp); 1288a3590dacSDaniel P. Berrange EnumProperty *enumprop; 1289a3590dacSDaniel P. Berrange 1290a3590dacSDaniel P. Berrange if (prop == NULL) { 1291a3590dacSDaniel P. Berrange return 0; 1292a3590dacSDaniel P. Berrange } 1293a3590dacSDaniel P. Berrange 1294a3590dacSDaniel P. Berrange if (!g_str_equal(prop->type, typename)) { 1295a3590dacSDaniel P. Berrange error_setg(errp, "Property %s on %s is not '%s' enum type", 1296a3590dacSDaniel P. Berrange name, object_class_get_name( 1297a3590dacSDaniel P. Berrange object_get_class(obj)), typename); 1298a3590dacSDaniel P. Berrange return 0; 1299a3590dacSDaniel P. Berrange } 1300a3590dacSDaniel P. Berrange 1301a3590dacSDaniel P. Berrange enumprop = prop->opaque; 13021f21772dSHu Tao 13033b098d56SEric Blake v = string_output_visitor_new(false, &str); 1304e7ca5656SEric Blake object_property_get(obj, v, name, &err); 13054715d42eSMarkus Armbruster if (err) { 13064715d42eSMarkus Armbruster error_propagate(errp, err); 1307e7ca5656SEric Blake visit_free(v); 13084715d42eSMarkus Armbruster return 0; 13094715d42eSMarkus Armbruster } 13103b098d56SEric Blake visit_complete(v, &str); 1311e7ca5656SEric Blake visit_free(v); 13127a0525c7SEric Blake v = string_input_visitor_new(str); 1313f7abe0ecSMarc-André Lureau visit_type_enum(v, name, &ret, enumprop->lookup, errp); 1314976620acSChen Fan 1315976620acSChen Fan g_free(str); 13167a0525c7SEric Blake visit_free(v); 13171f21772dSHu Tao 13181f21772dSHu Tao return ret; 13191f21772dSHu Tao } 13201f21772dSHu Tao 13211f21772dSHu Tao void object_property_get_uint16List(Object *obj, const char *name, 13221f21772dSHu Tao uint16List **list, Error **errp) 13231f21772dSHu Tao { 13244715d42eSMarkus Armbruster Error *err = NULL; 13257a0525c7SEric Blake Visitor *v; 1326976620acSChen Fan char *str; 13271f21772dSHu Tao 13283b098d56SEric Blake v = string_output_visitor_new(false, &str); 13293b098d56SEric Blake object_property_get(obj, v, name, &err); 13304715d42eSMarkus Armbruster if (err) { 13314715d42eSMarkus Armbruster error_propagate(errp, err); 13324715d42eSMarkus Armbruster goto out; 13334715d42eSMarkus Armbruster } 13343b098d56SEric Blake visit_complete(v, &str); 13353b098d56SEric Blake visit_free(v); 13367a0525c7SEric Blake v = string_input_visitor_new(str); 13377a0525c7SEric Blake visit_type_uint16List(v, NULL, list, errp); 1338976620acSChen Fan 1339976620acSChen Fan g_free(str); 13404715d42eSMarkus Armbruster out: 13413b098d56SEric Blake visit_free(v); 13421f21772dSHu Tao } 13431f21772dSHu Tao 1344b2cd7deeSPaolo Bonzini void object_property_parse(Object *obj, const char *string, 1345b2cd7deeSPaolo Bonzini const char *name, Error **errp) 1346b2cd7deeSPaolo Bonzini { 13477a0525c7SEric Blake Visitor *v = string_input_visitor_new(string); 13487a0525c7SEric Blake object_property_set(obj, v, name, errp); 13497a0525c7SEric Blake visit_free(v); 1350b2cd7deeSPaolo Bonzini } 1351b2cd7deeSPaolo Bonzini 13520b7593e0SPaolo Bonzini char *object_property_print(Object *obj, const char *name, bool human, 1353b2cd7deeSPaolo Bonzini Error **errp) 1354b2cd7deeSPaolo Bonzini { 13553b098d56SEric Blake Visitor *v; 13563a53009fSGonglei char *string = NULL; 13573a53009fSGonglei Error *local_err = NULL; 1358b2cd7deeSPaolo Bonzini 13593b098d56SEric Blake v = string_output_visitor_new(human, &string); 13603b098d56SEric Blake object_property_get(obj, v, name, &local_err); 13613a53009fSGonglei if (local_err) { 13623a53009fSGonglei error_propagate(errp, local_err); 13633a53009fSGonglei goto out; 13643a53009fSGonglei } 13653a53009fSGonglei 13663b098d56SEric Blake visit_complete(v, &string); 13673a53009fSGonglei 13683a53009fSGonglei out: 13693b098d56SEric Blake visit_free(v); 1370b2cd7deeSPaolo Bonzini return string; 1371b2cd7deeSPaolo Bonzini } 1372b2cd7deeSPaolo Bonzini 137357c9fafeSAnthony Liguori const char *object_property_get_type(Object *obj, const char *name, Error **errp) 137457c9fafeSAnthony Liguori { 137589bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 137657c9fafeSAnthony Liguori if (prop == NULL) { 137757c9fafeSAnthony Liguori return NULL; 137857c9fafeSAnthony Liguori } 137957c9fafeSAnthony Liguori 138057c9fafeSAnthony Liguori return prop->type; 138157c9fafeSAnthony Liguori } 138257c9fafeSAnthony Liguori 138357c9fafeSAnthony Liguori Object *object_get_root(void) 138457c9fafeSAnthony Liguori { 13858b45d447SAnthony Liguori static Object *root; 138657c9fafeSAnthony Liguori 13878b45d447SAnthony Liguori if (!root) { 13888b45d447SAnthony Liguori root = object_new("container"); 138957c9fafeSAnthony Liguori } 139057c9fafeSAnthony Liguori 13918b45d447SAnthony Liguori return root; 139257c9fafeSAnthony Liguori } 139357c9fafeSAnthony Liguori 1394bc2256c4SDaniel P. Berrange Object *object_get_objects_root(void) 1395bc2256c4SDaniel P. Berrange { 1396bc2256c4SDaniel P. Berrange return container_get(object_get_root(), "/objects"); 1397bc2256c4SDaniel P. Berrange } 1398bc2256c4SDaniel P. Berrange 13997c47c4eaSPeter Xu Object *object_get_internal_root(void) 14007c47c4eaSPeter Xu { 14017c47c4eaSPeter Xu static Object *internal_root; 14027c47c4eaSPeter Xu 14037c47c4eaSPeter Xu if (!internal_root) { 14047c47c4eaSPeter Xu internal_root = object_new("container"); 14057c47c4eaSPeter Xu } 14067c47c4eaSPeter Xu 14077c47c4eaSPeter Xu return internal_root; 14087c47c4eaSPeter Xu } 14097c47c4eaSPeter Xu 1410d7bce999SEric Blake static void object_get_child_property(Object *obj, Visitor *v, 1411d7bce999SEric Blake const char *name, void *opaque, 1412d7bce999SEric Blake Error **errp) 141357c9fafeSAnthony Liguori { 141457c9fafeSAnthony Liguori Object *child = opaque; 141557c9fafeSAnthony Liguori gchar *path; 141657c9fafeSAnthony Liguori 141757c9fafeSAnthony Liguori path = object_get_canonical_path(child); 141851e72bc1SEric Blake visit_type_str(v, name, &path, errp); 141957c9fafeSAnthony Liguori g_free(path); 142057c9fafeSAnthony Liguori } 142157c9fafeSAnthony Liguori 142264607d08SPaolo Bonzini static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part) 142364607d08SPaolo Bonzini { 142464607d08SPaolo Bonzini return opaque; 142564607d08SPaolo Bonzini } 142664607d08SPaolo Bonzini 1427db85b575SAnthony Liguori static void object_finalize_child_property(Object *obj, const char *name, 1428db85b575SAnthony Liguori void *opaque) 1429db85b575SAnthony Liguori { 1430db85b575SAnthony Liguori Object *child = opaque; 1431db85b575SAnthony Liguori 1432bffc687dSPaolo Bonzini if (child->class->unparent) { 1433bffc687dSPaolo Bonzini (child->class->unparent)(child); 1434bffc687dSPaolo Bonzini } 1435bffc687dSPaolo Bonzini child->parent = NULL; 1436db85b575SAnthony Liguori object_unref(child); 1437db85b575SAnthony Liguori } 1438db85b575SAnthony Liguori 143957c9fafeSAnthony Liguori void object_property_add_child(Object *obj, const char *name, 144057c9fafeSAnthony Liguori Object *child, Error **errp) 144157c9fafeSAnthony Liguori { 1442b0ed5e9fSPaolo Bonzini Error *local_err = NULL; 144357c9fafeSAnthony Liguori gchar *type; 144464607d08SPaolo Bonzini ObjectProperty *op; 144557c9fafeSAnthony Liguori 14468faa2f85SPeter Crosthwaite if (child->parent != NULL) { 14478faa2f85SPeter Crosthwaite error_setg(errp, "child object is already parented"); 14488faa2f85SPeter Crosthwaite return; 14498faa2f85SPeter Crosthwaite } 14508faa2f85SPeter Crosthwaite 145157c9fafeSAnthony Liguori type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); 145257c9fafeSAnthony Liguori 145364607d08SPaolo Bonzini op = object_property_add(obj, name, type, object_get_child_property, NULL, 1454b0ed5e9fSPaolo Bonzini object_finalize_child_property, child, &local_err); 1455b0ed5e9fSPaolo Bonzini if (local_err) { 1456b0ed5e9fSPaolo Bonzini error_propagate(errp, local_err); 1457b0ed5e9fSPaolo Bonzini goto out; 1458b0ed5e9fSPaolo Bonzini } 145964607d08SPaolo Bonzini 146064607d08SPaolo Bonzini op->resolve = object_resolve_child_property; 146157c9fafeSAnthony Liguori object_ref(child); 146257c9fafeSAnthony Liguori child->parent = obj; 146357c9fafeSAnthony Liguori 1464b0ed5e9fSPaolo Bonzini out: 146557c9fafeSAnthony Liguori g_free(type); 146657c9fafeSAnthony Liguori } 146757c9fafeSAnthony Liguori 14688f5d58efSIgor Mammedov void object_property_allow_set_link(const Object *obj, const char *name, 146939f72ef9SStefan Hajnoczi Object *val, Error **errp) 147039f72ef9SStefan Hajnoczi { 147139f72ef9SStefan Hajnoczi /* Allow the link to be set, always */ 147239f72ef9SStefan Hajnoczi } 147339f72ef9SStefan Hajnoczi 14749561fda8SStefan Hajnoczi typedef struct { 14759561fda8SStefan Hajnoczi Object **child; 14768f5d58efSIgor Mammedov void (*check)(const Object *, const char *, Object *, Error **); 14779561fda8SStefan Hajnoczi ObjectPropertyLinkFlags flags; 14789561fda8SStefan Hajnoczi } LinkProperty; 14799561fda8SStefan Hajnoczi 1480d7bce999SEric Blake static void object_get_link_property(Object *obj, Visitor *v, 1481d7bce999SEric Blake const char *name, void *opaque, 1482d7bce999SEric Blake Error **errp) 148357c9fafeSAnthony Liguori { 14849561fda8SStefan Hajnoczi LinkProperty *lprop = opaque; 14859561fda8SStefan Hajnoczi Object **child = lprop->child; 148657c9fafeSAnthony Liguori gchar *path; 148757c9fafeSAnthony Liguori 148857c9fafeSAnthony Liguori if (*child) { 148957c9fafeSAnthony Liguori path = object_get_canonical_path(*child); 149051e72bc1SEric Blake visit_type_str(v, name, &path, errp); 149157c9fafeSAnthony Liguori g_free(path); 149257c9fafeSAnthony Liguori } else { 149357c9fafeSAnthony Liguori path = (gchar *)""; 149451e72bc1SEric Blake visit_type_str(v, name, &path, errp); 149557c9fafeSAnthony Liguori } 149657c9fafeSAnthony Liguori } 149757c9fafeSAnthony Liguori 1498f5ec6704SStefan Hajnoczi /* 1499f5ec6704SStefan Hajnoczi * object_resolve_link: 1500f5ec6704SStefan Hajnoczi * 1501f5ec6704SStefan Hajnoczi * Lookup an object and ensure its type matches the link property type. This 1502f5ec6704SStefan Hajnoczi * is similar to object_resolve_path() except type verification against the 1503f5ec6704SStefan Hajnoczi * link property is performed. 1504f5ec6704SStefan Hajnoczi * 1505f5ec6704SStefan Hajnoczi * Returns: The matched object or NULL on path lookup failures. 1506f5ec6704SStefan Hajnoczi */ 1507f5ec6704SStefan Hajnoczi static Object *object_resolve_link(Object *obj, const char *name, 1508f5ec6704SStefan Hajnoczi const char *path, Error **errp) 1509f5ec6704SStefan Hajnoczi { 1510f5ec6704SStefan Hajnoczi const char *type; 1511f5ec6704SStefan Hajnoczi gchar *target_type; 1512f5ec6704SStefan Hajnoczi bool ambiguous = false; 1513f5ec6704SStefan Hajnoczi Object *target; 1514f5ec6704SStefan Hajnoczi 1515f5ec6704SStefan Hajnoczi /* Go from link<FOO> to FOO. */ 1516f5ec6704SStefan Hajnoczi type = object_property_get_type(obj, name, NULL); 1517f5ec6704SStefan Hajnoczi target_type = g_strndup(&type[5], strlen(type) - 6); 1518f5ec6704SStefan Hajnoczi target = object_resolve_path_type(path, target_type, &ambiguous); 1519f5ec6704SStefan Hajnoczi 1520f5ec6704SStefan Hajnoczi if (ambiguous) { 1521455b0fdeSEric Blake error_setg(errp, "Path '%s' does not uniquely identify an object", 1522455b0fdeSEric Blake path); 1523f5ec6704SStefan Hajnoczi } else if (!target) { 1524f5ec6704SStefan Hajnoczi target = object_resolve_path(path, &ambiguous); 1525f5ec6704SStefan Hajnoczi if (target || ambiguous) { 1526c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type); 1527f5ec6704SStefan Hajnoczi } else { 152875158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 152975158ebbSMarkus Armbruster "Device '%s' not found", path); 1530f5ec6704SStefan Hajnoczi } 1531f5ec6704SStefan Hajnoczi target = NULL; 1532f5ec6704SStefan Hajnoczi } 1533f5ec6704SStefan Hajnoczi g_free(target_type); 1534f5ec6704SStefan Hajnoczi 1535f5ec6704SStefan Hajnoczi return target; 1536f5ec6704SStefan Hajnoczi } 1537f5ec6704SStefan Hajnoczi 1538d7bce999SEric Blake static void object_set_link_property(Object *obj, Visitor *v, 1539d7bce999SEric Blake const char *name, void *opaque, 1540d7bce999SEric Blake Error **errp) 154157c9fafeSAnthony Liguori { 1542c6aed983SStefan Hajnoczi Error *local_err = NULL; 15439561fda8SStefan Hajnoczi LinkProperty *prop = opaque; 15449561fda8SStefan Hajnoczi Object **child = prop->child; 1545c6aed983SStefan Hajnoczi Object *old_target = *child; 1546c6aed983SStefan Hajnoczi Object *new_target = NULL; 1547c6aed983SStefan Hajnoczi char *path = NULL; 154857c9fafeSAnthony Liguori 154951e72bc1SEric Blake visit_type_str(v, name, &path, &local_err); 155057c9fafeSAnthony Liguori 1551c6aed983SStefan Hajnoczi if (!local_err && strcmp(path, "") != 0) { 1552c6aed983SStefan Hajnoczi new_target = object_resolve_link(obj, name, path, &local_err); 155311e35bfdSPaolo Bonzini } 155457c9fafeSAnthony Liguori 155557c9fafeSAnthony Liguori g_free(path); 1556c6aed983SStefan Hajnoczi if (local_err) { 1557c6aed983SStefan Hajnoczi error_propagate(errp, local_err); 1558c6aed983SStefan Hajnoczi return; 1559c6aed983SStefan Hajnoczi } 1560f0cdc966SAlexander Barabash 156139f72ef9SStefan Hajnoczi prop->check(obj, name, new_target, &local_err); 156239f72ef9SStefan Hajnoczi if (local_err) { 156339f72ef9SStefan Hajnoczi error_propagate(errp, local_err); 156439f72ef9SStefan Hajnoczi return; 156539f72ef9SStefan Hajnoczi } 156639f72ef9SStefan Hajnoczi 1567c6aed983SStefan Hajnoczi object_ref(new_target); 1568c6aed983SStefan Hajnoczi *child = new_target; 1569f0cdc966SAlexander Barabash object_unref(old_target); 1570f0cdc966SAlexander Barabash } 157157c9fafeSAnthony Liguori 157264607d08SPaolo Bonzini static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part) 157364607d08SPaolo Bonzini { 157464607d08SPaolo Bonzini LinkProperty *lprop = opaque; 157564607d08SPaolo Bonzini 157664607d08SPaolo Bonzini return *lprop->child; 157764607d08SPaolo Bonzini } 157864607d08SPaolo Bonzini 15799561fda8SStefan Hajnoczi static void object_release_link_property(Object *obj, const char *name, 15809561fda8SStefan Hajnoczi void *opaque) 15819561fda8SStefan Hajnoczi { 15829561fda8SStefan Hajnoczi LinkProperty *prop = opaque; 15839561fda8SStefan Hajnoczi 15849561fda8SStefan Hajnoczi if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) { 15859561fda8SStefan Hajnoczi object_unref(*prop->child); 15869561fda8SStefan Hajnoczi } 15879561fda8SStefan Hajnoczi g_free(prop); 15889561fda8SStefan Hajnoczi } 15899561fda8SStefan Hajnoczi 159057c9fafeSAnthony Liguori void object_property_add_link(Object *obj, const char *name, 159157c9fafeSAnthony Liguori const char *type, Object **child, 15928f5d58efSIgor Mammedov void (*check)(const Object *, const char *, 159339f72ef9SStefan Hajnoczi Object *, Error **), 15949561fda8SStefan Hajnoczi ObjectPropertyLinkFlags flags, 159557c9fafeSAnthony Liguori Error **errp) 159657c9fafeSAnthony Liguori { 15979561fda8SStefan Hajnoczi Error *local_err = NULL; 15989561fda8SStefan Hajnoczi LinkProperty *prop = g_malloc(sizeof(*prop)); 159957c9fafeSAnthony Liguori gchar *full_type; 160064607d08SPaolo Bonzini ObjectProperty *op; 160157c9fafeSAnthony Liguori 16029561fda8SStefan Hajnoczi prop->child = child; 160339f72ef9SStefan Hajnoczi prop->check = check; 16049561fda8SStefan Hajnoczi prop->flags = flags; 16059561fda8SStefan Hajnoczi 160657c9fafeSAnthony Liguori full_type = g_strdup_printf("link<%s>", type); 160757c9fafeSAnthony Liguori 160864607d08SPaolo Bonzini op = object_property_add(obj, name, full_type, 160957c9fafeSAnthony Liguori object_get_link_property, 161039f72ef9SStefan Hajnoczi check ? object_set_link_property : NULL, 16119561fda8SStefan Hajnoczi object_release_link_property, 16129561fda8SStefan Hajnoczi prop, 16139561fda8SStefan Hajnoczi &local_err); 16149561fda8SStefan Hajnoczi if (local_err) { 16159561fda8SStefan Hajnoczi error_propagate(errp, local_err); 16169561fda8SStefan Hajnoczi g_free(prop); 161764607d08SPaolo Bonzini goto out; 16189561fda8SStefan Hajnoczi } 161957c9fafeSAnthony Liguori 162064607d08SPaolo Bonzini op->resolve = object_resolve_link_property; 162164607d08SPaolo Bonzini 162264607d08SPaolo Bonzini out: 162357c9fafeSAnthony Liguori g_free(full_type); 162457c9fafeSAnthony Liguori } 162557c9fafeSAnthony Liguori 1626fb9e7e33SPaolo Bonzini void object_property_add_const_link(Object *obj, const char *name, 1627fb9e7e33SPaolo Bonzini Object *target, Error **errp) 1628fb9e7e33SPaolo Bonzini { 1629fb9e7e33SPaolo Bonzini char *link_type; 1630fb9e7e33SPaolo Bonzini ObjectProperty *op; 1631fb9e7e33SPaolo Bonzini 1632fb9e7e33SPaolo Bonzini link_type = g_strdup_printf("link<%s>", object_get_typename(target)); 1633fb9e7e33SPaolo Bonzini op = object_property_add(obj, name, link_type, 1634fb9e7e33SPaolo Bonzini object_get_child_property, NULL, 1635fb9e7e33SPaolo Bonzini NULL, target, errp); 1636fb9e7e33SPaolo Bonzini if (op != NULL) { 1637fb9e7e33SPaolo Bonzini op->resolve = object_resolve_child_property; 1638fb9e7e33SPaolo Bonzini } 1639fb9e7e33SPaolo Bonzini g_free(link_type); 1640fb9e7e33SPaolo Bonzini } 1641fb9e7e33SPaolo Bonzini 164211f590b1SStefan Hajnoczi gchar *object_get_canonical_path_component(Object *obj) 164357c9fafeSAnthony Liguori { 164457c9fafeSAnthony Liguori ObjectProperty *prop = NULL; 1645b604a854SPavel Fedin GHashTableIter iter; 164657c9fafeSAnthony Liguori 164711f590b1SStefan Hajnoczi g_assert(obj); 164857c9fafeSAnthony Liguori g_assert(obj->parent != NULL); 164957c9fafeSAnthony Liguori 1650b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->parent->properties); 1651b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 16525d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 165357c9fafeSAnthony Liguori continue; 165457c9fafeSAnthony Liguori } 165557c9fafeSAnthony Liguori 165657c9fafeSAnthony Liguori if (prop->opaque == obj) { 165711f590b1SStefan Hajnoczi return g_strdup(prop->name); 165857c9fafeSAnthony Liguori } 165957c9fafeSAnthony Liguori } 166057c9fafeSAnthony Liguori 166111f590b1SStefan Hajnoczi /* obj had a parent but was not a child, should never happen */ 166211f590b1SStefan Hajnoczi g_assert_not_reached(); 166311f590b1SStefan Hajnoczi return NULL; 166411f590b1SStefan Hajnoczi } 166511f590b1SStefan Hajnoczi 166611f590b1SStefan Hajnoczi gchar *object_get_canonical_path(Object *obj) 166711f590b1SStefan Hajnoczi { 166811f590b1SStefan Hajnoczi Object *root = object_get_root(); 166911f590b1SStefan Hajnoczi char *newpath, *path = NULL; 167011f590b1SStefan Hajnoczi 167111f590b1SStefan Hajnoczi while (obj != root) { 167211f590b1SStefan Hajnoczi char *component = object_get_canonical_path_component(obj); 167311f590b1SStefan Hajnoczi 167411f590b1SStefan Hajnoczi if (path) { 167511f590b1SStefan Hajnoczi newpath = g_strdup_printf("%s/%s", component, path); 167611f590b1SStefan Hajnoczi g_free(component); 167711f590b1SStefan Hajnoczi g_free(path); 167811f590b1SStefan Hajnoczi path = newpath; 167911f590b1SStefan Hajnoczi } else { 168011f590b1SStefan Hajnoczi path = component; 168111f590b1SStefan Hajnoczi } 168257c9fafeSAnthony Liguori 168357c9fafeSAnthony Liguori obj = obj->parent; 168457c9fafeSAnthony Liguori } 168557c9fafeSAnthony Liguori 168611f590b1SStefan Hajnoczi newpath = g_strdup_printf("/%s", path ? path : ""); 168757c9fafeSAnthony Liguori g_free(path); 168857c9fafeSAnthony Liguori 168957c9fafeSAnthony Liguori return newpath; 169057c9fafeSAnthony Liguori } 169157c9fafeSAnthony Liguori 16923e84b483SAndreas Färber Object *object_resolve_path_component(Object *parent, const gchar *part) 1693a612b2a6SPaolo Bonzini { 169489bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(parent, part, NULL); 1695a612b2a6SPaolo Bonzini if (prop == NULL) { 1696a612b2a6SPaolo Bonzini return NULL; 1697a612b2a6SPaolo Bonzini } 1698a612b2a6SPaolo Bonzini 169964607d08SPaolo Bonzini if (prop->resolve) { 170064607d08SPaolo Bonzini return prop->resolve(parent, prop->opaque, part); 1701a612b2a6SPaolo Bonzini } else { 1702a612b2a6SPaolo Bonzini return NULL; 1703a612b2a6SPaolo Bonzini } 1704a612b2a6SPaolo Bonzini } 1705a612b2a6SPaolo Bonzini 170657c9fafeSAnthony Liguori static Object *object_resolve_abs_path(Object *parent, 170757c9fafeSAnthony Liguori gchar **parts, 170802fe2db6SPaolo Bonzini const char *typename, 170957c9fafeSAnthony Liguori int index) 171057c9fafeSAnthony Liguori { 171157c9fafeSAnthony Liguori Object *child; 171257c9fafeSAnthony Liguori 171357c9fafeSAnthony Liguori if (parts[index] == NULL) { 171402fe2db6SPaolo Bonzini return object_dynamic_cast(parent, typename); 171557c9fafeSAnthony Liguori } 171657c9fafeSAnthony Liguori 171757c9fafeSAnthony Liguori if (strcmp(parts[index], "") == 0) { 171802fe2db6SPaolo Bonzini return object_resolve_abs_path(parent, parts, typename, index + 1); 171957c9fafeSAnthony Liguori } 172057c9fafeSAnthony Liguori 1721a612b2a6SPaolo Bonzini child = object_resolve_path_component(parent, parts[index]); 172257c9fafeSAnthony Liguori if (!child) { 172357c9fafeSAnthony Liguori return NULL; 172457c9fafeSAnthony Liguori } 172557c9fafeSAnthony Liguori 172602fe2db6SPaolo Bonzini return object_resolve_abs_path(child, parts, typename, index + 1); 172757c9fafeSAnthony Liguori } 172857c9fafeSAnthony Liguori 172957c9fafeSAnthony Liguori static Object *object_resolve_partial_path(Object *parent, 173057c9fafeSAnthony Liguori gchar **parts, 173102fe2db6SPaolo Bonzini const char *typename, 173257c9fafeSAnthony Liguori bool *ambiguous) 173357c9fafeSAnthony Liguori { 173457c9fafeSAnthony Liguori Object *obj; 1735b604a854SPavel Fedin GHashTableIter iter; 173657c9fafeSAnthony Liguori ObjectProperty *prop; 173757c9fafeSAnthony Liguori 173802fe2db6SPaolo Bonzini obj = object_resolve_abs_path(parent, parts, typename, 0); 173957c9fafeSAnthony Liguori 1740b604a854SPavel Fedin g_hash_table_iter_init(&iter, parent->properties); 1741b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 174257c9fafeSAnthony Liguori Object *found; 174357c9fafeSAnthony Liguori 17445d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 174557c9fafeSAnthony Liguori continue; 174657c9fafeSAnthony Liguori } 174757c9fafeSAnthony Liguori 174802fe2db6SPaolo Bonzini found = object_resolve_partial_path(prop->opaque, parts, 174902fe2db6SPaolo Bonzini typename, ambiguous); 175057c9fafeSAnthony Liguori if (found) { 175157c9fafeSAnthony Liguori if (obj) { 175257c9fafeSAnthony Liguori *ambiguous = true; 175357c9fafeSAnthony Liguori return NULL; 175457c9fafeSAnthony Liguori } 175557c9fafeSAnthony Liguori obj = found; 175657c9fafeSAnthony Liguori } 175757c9fafeSAnthony Liguori 1758ebcc479eSEduardo Habkost if (*ambiguous) { 175957c9fafeSAnthony Liguori return NULL; 176057c9fafeSAnthony Liguori } 176157c9fafeSAnthony Liguori } 176257c9fafeSAnthony Liguori 176357c9fafeSAnthony Liguori return obj; 176457c9fafeSAnthony Liguori } 176557c9fafeSAnthony Liguori 176602fe2db6SPaolo Bonzini Object *object_resolve_path_type(const char *path, const char *typename, 1767ebcc479eSEduardo Habkost bool *ambiguousp) 176857c9fafeSAnthony Liguori { 176957c9fafeSAnthony Liguori Object *obj; 177057c9fafeSAnthony Liguori gchar **parts; 177157c9fafeSAnthony Liguori 177257c9fafeSAnthony Liguori parts = g_strsplit(path, "/", 0); 17732e1103f6SPaolo Bonzini assert(parts); 177457c9fafeSAnthony Liguori 17752e1103f6SPaolo Bonzini if (parts[0] == NULL || strcmp(parts[0], "") != 0) { 1776ebcc479eSEduardo Habkost bool ambiguous = false; 177702fe2db6SPaolo Bonzini obj = object_resolve_partial_path(object_get_root(), parts, 1778ebcc479eSEduardo Habkost typename, &ambiguous); 1779ebcc479eSEduardo Habkost if (ambiguousp) { 1780ebcc479eSEduardo Habkost *ambiguousp = ambiguous; 1781ebcc479eSEduardo Habkost } 178257c9fafeSAnthony Liguori } else { 178302fe2db6SPaolo Bonzini obj = object_resolve_abs_path(object_get_root(), parts, typename, 1); 178457c9fafeSAnthony Liguori } 178557c9fafeSAnthony Liguori 178657c9fafeSAnthony Liguori g_strfreev(parts); 178757c9fafeSAnthony Liguori 178857c9fafeSAnthony Liguori return obj; 178957c9fafeSAnthony Liguori } 179057c9fafeSAnthony Liguori 179102fe2db6SPaolo Bonzini Object *object_resolve_path(const char *path, bool *ambiguous) 179202fe2db6SPaolo Bonzini { 179302fe2db6SPaolo Bonzini return object_resolve_path_type(path, TYPE_OBJECT, ambiguous); 179402fe2db6SPaolo Bonzini } 179502fe2db6SPaolo Bonzini 179657c9fafeSAnthony Liguori typedef struct StringProperty 179757c9fafeSAnthony Liguori { 179857c9fafeSAnthony Liguori char *(*get)(Object *, Error **); 179957c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **); 180057c9fafeSAnthony Liguori } StringProperty; 180157c9fafeSAnthony Liguori 1802d7bce999SEric Blake static void property_get_str(Object *obj, Visitor *v, const char *name, 1803d7bce999SEric Blake void *opaque, Error **errp) 180457c9fafeSAnthony Liguori { 180557c9fafeSAnthony Liguori StringProperty *prop = opaque; 180657c9fafeSAnthony Liguori char *value; 1807e1c8237dSMarkus Armbruster Error *err = NULL; 180857c9fafeSAnthony Liguori 1809e1c8237dSMarkus Armbruster value = prop->get(obj, &err); 1810e1c8237dSMarkus Armbruster if (err) { 1811e1c8237dSMarkus Armbruster error_propagate(errp, err); 1812e1c8237dSMarkus Armbruster return; 1813e1c8237dSMarkus Armbruster } 1814e1c8237dSMarkus Armbruster 181551e72bc1SEric Blake visit_type_str(v, name, &value, errp); 181657c9fafeSAnthony Liguori g_free(value); 181757c9fafeSAnthony Liguori } 181857c9fafeSAnthony Liguori 1819d7bce999SEric Blake static void property_set_str(Object *obj, Visitor *v, const char *name, 1820d7bce999SEric Blake void *opaque, Error **errp) 182157c9fafeSAnthony Liguori { 182257c9fafeSAnthony Liguori StringProperty *prop = opaque; 182357c9fafeSAnthony Liguori char *value; 182457c9fafeSAnthony Liguori Error *local_err = NULL; 182557c9fafeSAnthony Liguori 182651e72bc1SEric Blake visit_type_str(v, name, &value, &local_err); 182757c9fafeSAnthony Liguori if (local_err) { 182857c9fafeSAnthony Liguori error_propagate(errp, local_err); 182957c9fafeSAnthony Liguori return; 183057c9fafeSAnthony Liguori } 183157c9fafeSAnthony Liguori 183257c9fafeSAnthony Liguori prop->set(obj, value, errp); 183357c9fafeSAnthony Liguori g_free(value); 183457c9fafeSAnthony Liguori } 183557c9fafeSAnthony Liguori 18367b7b7d18SPaolo Bonzini static void property_release_str(Object *obj, const char *name, 183757c9fafeSAnthony Liguori void *opaque) 183857c9fafeSAnthony Liguori { 183957c9fafeSAnthony Liguori StringProperty *prop = opaque; 184057c9fafeSAnthony Liguori g_free(prop); 184157c9fafeSAnthony Liguori } 184257c9fafeSAnthony Liguori 184357c9fafeSAnthony Liguori void object_property_add_str(Object *obj, const char *name, 184457c9fafeSAnthony Liguori char *(*get)(Object *, Error **), 184557c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **), 184657c9fafeSAnthony Liguori Error **errp) 184757c9fafeSAnthony Liguori { 1848a01aedc8SStefan Hajnoczi Error *local_err = NULL; 184957c9fafeSAnthony Liguori StringProperty *prop = g_malloc0(sizeof(*prop)); 185057c9fafeSAnthony Liguori 185157c9fafeSAnthony Liguori prop->get = get; 185257c9fafeSAnthony Liguori prop->set = set; 185357c9fafeSAnthony Liguori 185457c9fafeSAnthony Liguori object_property_add(obj, name, "string", 18557b7b7d18SPaolo Bonzini get ? property_get_str : NULL, 18567b7b7d18SPaolo Bonzini set ? property_set_str : NULL, 18577b7b7d18SPaolo Bonzini property_release_str, 1858a01aedc8SStefan Hajnoczi prop, &local_err); 1859a01aedc8SStefan Hajnoczi if (local_err) { 1860a01aedc8SStefan Hajnoczi error_propagate(errp, local_err); 1861a01aedc8SStefan Hajnoczi g_free(prop); 1862a01aedc8SStefan Hajnoczi } 186357c9fafeSAnthony Liguori } 1864745549c8SPaolo Bonzini 186516bf7f52SDaniel P. Berrange void object_class_property_add_str(ObjectClass *klass, const char *name, 186616bf7f52SDaniel P. Berrange char *(*get)(Object *, Error **), 186716bf7f52SDaniel P. Berrange void (*set)(Object *, const char *, 186816bf7f52SDaniel P. Berrange Error **), 186916bf7f52SDaniel P. Berrange Error **errp) 187016bf7f52SDaniel P. Berrange { 187116bf7f52SDaniel P. Berrange Error *local_err = NULL; 187216bf7f52SDaniel P. Berrange StringProperty *prop = g_malloc0(sizeof(*prop)); 187316bf7f52SDaniel P. Berrange 187416bf7f52SDaniel P. Berrange prop->get = get; 187516bf7f52SDaniel P. Berrange prop->set = set; 187616bf7f52SDaniel P. Berrange 187716bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "string", 187816bf7f52SDaniel P. Berrange get ? property_get_str : NULL, 187916bf7f52SDaniel P. Berrange set ? property_set_str : NULL, 188016bf7f52SDaniel P. Berrange property_release_str, 188116bf7f52SDaniel P. Berrange prop, &local_err); 188216bf7f52SDaniel P. Berrange if (local_err) { 188316bf7f52SDaniel P. Berrange error_propagate(errp, local_err); 188416bf7f52SDaniel P. Berrange g_free(prop); 188516bf7f52SDaniel P. Berrange } 188616bf7f52SDaniel P. Berrange } 188716bf7f52SDaniel P. Berrange 18880e558843SAnthony Liguori typedef struct BoolProperty 18890e558843SAnthony Liguori { 18900e558843SAnthony Liguori bool (*get)(Object *, Error **); 18910e558843SAnthony Liguori void (*set)(Object *, bool, Error **); 18920e558843SAnthony Liguori } BoolProperty; 18930e558843SAnthony Liguori 1894d7bce999SEric Blake static void property_get_bool(Object *obj, Visitor *v, const char *name, 1895d7bce999SEric Blake void *opaque, Error **errp) 18960e558843SAnthony Liguori { 18970e558843SAnthony Liguori BoolProperty *prop = opaque; 18980e558843SAnthony Liguori bool value; 18994715d42eSMarkus Armbruster Error *err = NULL; 19000e558843SAnthony Liguori 19014715d42eSMarkus Armbruster value = prop->get(obj, &err); 19024715d42eSMarkus Armbruster if (err) { 19034715d42eSMarkus Armbruster error_propagate(errp, err); 19044715d42eSMarkus Armbruster return; 19054715d42eSMarkus Armbruster } 19064715d42eSMarkus Armbruster 190751e72bc1SEric Blake visit_type_bool(v, name, &value, errp); 19080e558843SAnthony Liguori } 19090e558843SAnthony Liguori 1910d7bce999SEric Blake static void property_set_bool(Object *obj, Visitor *v, const char *name, 1911d7bce999SEric Blake void *opaque, Error **errp) 19120e558843SAnthony Liguori { 19130e558843SAnthony Liguori BoolProperty *prop = opaque; 19140e558843SAnthony Liguori bool value; 19150e558843SAnthony Liguori Error *local_err = NULL; 19160e558843SAnthony Liguori 191751e72bc1SEric Blake visit_type_bool(v, name, &value, &local_err); 19180e558843SAnthony Liguori if (local_err) { 19190e558843SAnthony Liguori error_propagate(errp, local_err); 19200e558843SAnthony Liguori return; 19210e558843SAnthony Liguori } 19220e558843SAnthony Liguori 19230e558843SAnthony Liguori prop->set(obj, value, errp); 19240e558843SAnthony Liguori } 19250e558843SAnthony Liguori 19260e558843SAnthony Liguori static void property_release_bool(Object *obj, const char *name, 19270e558843SAnthony Liguori void *opaque) 19280e558843SAnthony Liguori { 19290e558843SAnthony Liguori BoolProperty *prop = opaque; 19300e558843SAnthony Liguori g_free(prop); 19310e558843SAnthony Liguori } 19320e558843SAnthony Liguori 19330e558843SAnthony Liguori void object_property_add_bool(Object *obj, const char *name, 19340e558843SAnthony Liguori bool (*get)(Object *, Error **), 19350e558843SAnthony Liguori void (*set)(Object *, bool, Error **), 19360e558843SAnthony Liguori Error **errp) 19370e558843SAnthony Liguori { 1938a01aedc8SStefan Hajnoczi Error *local_err = NULL; 19390e558843SAnthony Liguori BoolProperty *prop = g_malloc0(sizeof(*prop)); 19400e558843SAnthony Liguori 19410e558843SAnthony Liguori prop->get = get; 19420e558843SAnthony Liguori prop->set = set; 19430e558843SAnthony Liguori 19440e558843SAnthony Liguori object_property_add(obj, name, "bool", 19450e558843SAnthony Liguori get ? property_get_bool : NULL, 19460e558843SAnthony Liguori set ? property_set_bool : NULL, 19470e558843SAnthony Liguori property_release_bool, 1948a01aedc8SStefan Hajnoczi prop, &local_err); 1949a01aedc8SStefan Hajnoczi if (local_err) { 1950a01aedc8SStefan Hajnoczi error_propagate(errp, local_err); 1951a01aedc8SStefan Hajnoczi g_free(prop); 1952a01aedc8SStefan Hajnoczi } 19530e558843SAnthony Liguori } 19540e558843SAnthony Liguori 195516bf7f52SDaniel P. Berrange void object_class_property_add_bool(ObjectClass *klass, const char *name, 195616bf7f52SDaniel P. Berrange bool (*get)(Object *, Error **), 195716bf7f52SDaniel P. Berrange void (*set)(Object *, bool, Error **), 195816bf7f52SDaniel P. Berrange Error **errp) 195916bf7f52SDaniel P. Berrange { 196016bf7f52SDaniel P. Berrange Error *local_err = NULL; 196116bf7f52SDaniel P. Berrange BoolProperty *prop = g_malloc0(sizeof(*prop)); 196216bf7f52SDaniel P. Berrange 196316bf7f52SDaniel P. Berrange prop->get = get; 196416bf7f52SDaniel P. Berrange prop->set = set; 196516bf7f52SDaniel P. Berrange 196616bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "bool", 196716bf7f52SDaniel P. Berrange get ? property_get_bool : NULL, 196816bf7f52SDaniel P. Berrange set ? property_set_bool : NULL, 196916bf7f52SDaniel P. Berrange property_release_bool, 197016bf7f52SDaniel P. Berrange prop, &local_err); 197116bf7f52SDaniel P. Berrange if (local_err) { 197216bf7f52SDaniel P. Berrange error_propagate(errp, local_err); 197316bf7f52SDaniel P. Berrange g_free(prop); 197416bf7f52SDaniel P. Berrange } 197516bf7f52SDaniel P. Berrange } 197616bf7f52SDaniel P. Berrange 1977d7bce999SEric Blake static void property_get_enum(Object *obj, Visitor *v, const char *name, 1978d7bce999SEric Blake void *opaque, Error **errp) 1979a8e3fbedSDaniel P. Berrange { 1980a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 1981a8e3fbedSDaniel P. Berrange int value; 19824715d42eSMarkus Armbruster Error *err = NULL; 1983a8e3fbedSDaniel P. Berrange 19844715d42eSMarkus Armbruster value = prop->get(obj, &err); 19854715d42eSMarkus Armbruster if (err) { 19864715d42eSMarkus Armbruster error_propagate(errp, err); 19874715d42eSMarkus Armbruster return; 19884715d42eSMarkus Armbruster } 19894715d42eSMarkus Armbruster 1990f7abe0ecSMarc-André Lureau visit_type_enum(v, name, &value, prop->lookup, errp); 1991a8e3fbedSDaniel P. Berrange } 1992a8e3fbedSDaniel P. Berrange 1993d7bce999SEric Blake static void property_set_enum(Object *obj, Visitor *v, const char *name, 1994d7bce999SEric Blake void *opaque, Error **errp) 1995a8e3fbedSDaniel P. Berrange { 1996a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 1997a8e3fbedSDaniel P. Berrange int value; 19984715d42eSMarkus Armbruster Error *err = NULL; 1999a8e3fbedSDaniel P. Berrange 2000f7abe0ecSMarc-André Lureau visit_type_enum(v, name, &value, prop->lookup, &err); 20014715d42eSMarkus Armbruster if (err) { 20024715d42eSMarkus Armbruster error_propagate(errp, err); 20034715d42eSMarkus Armbruster return; 20044715d42eSMarkus Armbruster } 2005a8e3fbedSDaniel P. Berrange prop->set(obj, value, errp); 2006a8e3fbedSDaniel P. Berrange } 2007a8e3fbedSDaniel P. Berrange 2008a8e3fbedSDaniel P. Berrange static void property_release_enum(Object *obj, const char *name, 2009a8e3fbedSDaniel P. Berrange void *opaque) 2010a8e3fbedSDaniel P. Berrange { 2011a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 2012a8e3fbedSDaniel P. Berrange g_free(prop); 2013a8e3fbedSDaniel P. Berrange } 2014a8e3fbedSDaniel P. Berrange 2015a8e3fbedSDaniel P. Berrange void object_property_add_enum(Object *obj, const char *name, 2016a8e3fbedSDaniel P. Berrange const char *typename, 2017f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, 2018a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **), 2019a8e3fbedSDaniel P. Berrange void (*set)(Object *, int, Error **), 2020a8e3fbedSDaniel P. Berrange Error **errp) 2021a8e3fbedSDaniel P. Berrange { 2022a8e3fbedSDaniel P. Berrange Error *local_err = NULL; 2023a8e3fbedSDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop)); 2024a8e3fbedSDaniel P. Berrange 2025f7abe0ecSMarc-André Lureau prop->lookup = lookup; 2026a8e3fbedSDaniel P. Berrange prop->get = get; 2027a8e3fbedSDaniel P. Berrange prop->set = set; 2028a8e3fbedSDaniel P. Berrange 2029a8e3fbedSDaniel P. Berrange object_property_add(obj, name, typename, 2030a8e3fbedSDaniel P. Berrange get ? property_get_enum : NULL, 2031a8e3fbedSDaniel P. Berrange set ? property_set_enum : NULL, 2032a8e3fbedSDaniel P. Berrange property_release_enum, 2033a8e3fbedSDaniel P. Berrange prop, &local_err); 2034a8e3fbedSDaniel P. Berrange if (local_err) { 2035a8e3fbedSDaniel P. Berrange error_propagate(errp, local_err); 2036a8e3fbedSDaniel P. Berrange g_free(prop); 2037a8e3fbedSDaniel P. Berrange } 2038a8e3fbedSDaniel P. Berrange } 2039a8e3fbedSDaniel P. Berrange 204016bf7f52SDaniel P. Berrange void object_class_property_add_enum(ObjectClass *klass, const char *name, 204116bf7f52SDaniel P. Berrange const char *typename, 2042f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, 204316bf7f52SDaniel P. Berrange int (*get)(Object *, Error **), 204416bf7f52SDaniel P. Berrange void (*set)(Object *, int, Error **), 204516bf7f52SDaniel P. Berrange Error **errp) 204616bf7f52SDaniel P. Berrange { 204716bf7f52SDaniel P. Berrange Error *local_err = NULL; 204816bf7f52SDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop)); 204916bf7f52SDaniel P. Berrange 2050f7abe0ecSMarc-André Lureau prop->lookup = lookup; 205116bf7f52SDaniel P. Berrange prop->get = get; 205216bf7f52SDaniel P. Berrange prop->set = set; 205316bf7f52SDaniel P. Berrange 205416bf7f52SDaniel P. Berrange object_class_property_add(klass, name, typename, 205516bf7f52SDaniel P. Berrange get ? property_get_enum : NULL, 205616bf7f52SDaniel P. Berrange set ? property_set_enum : NULL, 205716bf7f52SDaniel P. Berrange property_release_enum, 205816bf7f52SDaniel P. Berrange prop, &local_err); 205916bf7f52SDaniel P. Berrange if (local_err) { 206016bf7f52SDaniel P. Berrange error_propagate(errp, local_err); 206116bf7f52SDaniel P. Berrange g_free(prop); 206216bf7f52SDaniel P. Berrange } 206316bf7f52SDaniel P. Berrange } 206416bf7f52SDaniel P. Berrange 20658e099d14SDavid Gibson typedef struct TMProperty { 20668e099d14SDavid Gibson void (*get)(Object *, struct tm *, Error **); 20678e099d14SDavid Gibson } TMProperty; 20688e099d14SDavid Gibson 2069d7bce999SEric Blake static void property_get_tm(Object *obj, Visitor *v, const char *name, 2070d7bce999SEric Blake void *opaque, Error **errp) 20718e099d14SDavid Gibson { 20728e099d14SDavid Gibson TMProperty *prop = opaque; 20738e099d14SDavid Gibson Error *err = NULL; 20748e099d14SDavid Gibson struct tm value; 20758e099d14SDavid Gibson 20768e099d14SDavid Gibson prop->get(obj, &value, &err); 20778e099d14SDavid Gibson if (err) { 20788e099d14SDavid Gibson goto out; 20798e099d14SDavid Gibson } 20808e099d14SDavid Gibson 2081337283dfSEric Blake visit_start_struct(v, name, NULL, 0, &err); 20828e099d14SDavid Gibson if (err) { 20838e099d14SDavid Gibson goto out; 20848e099d14SDavid Gibson } 208551e72bc1SEric Blake visit_type_int32(v, "tm_year", &value.tm_year, &err); 20868e099d14SDavid Gibson if (err) { 20878e099d14SDavid Gibson goto out_end; 20888e099d14SDavid Gibson } 208951e72bc1SEric Blake visit_type_int32(v, "tm_mon", &value.tm_mon, &err); 20908e099d14SDavid Gibson if (err) { 20918e099d14SDavid Gibson goto out_end; 20928e099d14SDavid Gibson } 209351e72bc1SEric Blake visit_type_int32(v, "tm_mday", &value.tm_mday, &err); 20948e099d14SDavid Gibson if (err) { 20958e099d14SDavid Gibson goto out_end; 20968e099d14SDavid Gibson } 209751e72bc1SEric Blake visit_type_int32(v, "tm_hour", &value.tm_hour, &err); 20988e099d14SDavid Gibson if (err) { 20998e099d14SDavid Gibson goto out_end; 21008e099d14SDavid Gibson } 210151e72bc1SEric Blake visit_type_int32(v, "tm_min", &value.tm_min, &err); 21028e099d14SDavid Gibson if (err) { 21038e099d14SDavid Gibson goto out_end; 21048e099d14SDavid Gibson } 210551e72bc1SEric Blake visit_type_int32(v, "tm_sec", &value.tm_sec, &err); 21068e099d14SDavid Gibson if (err) { 21078e099d14SDavid Gibson goto out_end; 21088e099d14SDavid Gibson } 210915c2f669SEric Blake visit_check_struct(v, &err); 21108e099d14SDavid Gibson out_end: 21111158bb2aSEric Blake visit_end_struct(v, NULL); 21128e099d14SDavid Gibson out: 21138e099d14SDavid Gibson error_propagate(errp, err); 21148e099d14SDavid Gibson 21158e099d14SDavid Gibson } 21168e099d14SDavid Gibson 21178e099d14SDavid Gibson static void property_release_tm(Object *obj, const char *name, 21188e099d14SDavid Gibson void *opaque) 21198e099d14SDavid Gibson { 21208e099d14SDavid Gibson TMProperty *prop = opaque; 21218e099d14SDavid Gibson g_free(prop); 21228e099d14SDavid Gibson } 21238e099d14SDavid Gibson 21248e099d14SDavid Gibson void object_property_add_tm(Object *obj, const char *name, 21258e099d14SDavid Gibson void (*get)(Object *, struct tm *, Error **), 21268e099d14SDavid Gibson Error **errp) 21278e099d14SDavid Gibson { 21288e099d14SDavid Gibson Error *local_err = NULL; 21298e099d14SDavid Gibson TMProperty *prop = g_malloc0(sizeof(*prop)); 21308e099d14SDavid Gibson 21318e099d14SDavid Gibson prop->get = get; 21328e099d14SDavid Gibson 21338e099d14SDavid Gibson object_property_add(obj, name, "struct tm", 21348e099d14SDavid Gibson get ? property_get_tm : NULL, NULL, 21358e099d14SDavid Gibson property_release_tm, 21368e099d14SDavid Gibson prop, &local_err); 21378e099d14SDavid Gibson if (local_err) { 21388e099d14SDavid Gibson error_propagate(errp, local_err); 21398e099d14SDavid Gibson g_free(prop); 21408e099d14SDavid Gibson } 21418e099d14SDavid Gibson } 21428e099d14SDavid Gibson 214316bf7f52SDaniel P. Berrange void object_class_property_add_tm(ObjectClass *klass, const char *name, 214416bf7f52SDaniel P. Berrange void (*get)(Object *, struct tm *, Error **), 214516bf7f52SDaniel P. Berrange Error **errp) 214616bf7f52SDaniel P. Berrange { 214716bf7f52SDaniel P. Berrange Error *local_err = NULL; 214816bf7f52SDaniel P. Berrange TMProperty *prop = g_malloc0(sizeof(*prop)); 214916bf7f52SDaniel P. Berrange 215016bf7f52SDaniel P. Berrange prop->get = get; 215116bf7f52SDaniel P. Berrange 215216bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "struct tm", 215316bf7f52SDaniel P. Berrange get ? property_get_tm : NULL, NULL, 215416bf7f52SDaniel P. Berrange property_release_tm, 215516bf7f52SDaniel P. Berrange prop, &local_err); 215616bf7f52SDaniel P. Berrange if (local_err) { 215716bf7f52SDaniel P. Berrange error_propagate(errp, local_err); 215816bf7f52SDaniel P. Berrange g_free(prop); 215916bf7f52SDaniel P. Berrange } 216016bf7f52SDaniel P. Berrange } 216116bf7f52SDaniel P. Berrange 21622f262e06SPaolo Bonzini static char *qdev_get_type(Object *obj, Error **errp) 21632f262e06SPaolo Bonzini { 21642f262e06SPaolo Bonzini return g_strdup(object_get_typename(obj)); 21652f262e06SPaolo Bonzini } 21662f262e06SPaolo Bonzini 2167d7bce999SEric Blake static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, 2168d7bce999SEric Blake void *opaque, Error **errp) 2169e732ea63SMichael S. Tsirkin { 2170e732ea63SMichael S. Tsirkin uint8_t value = *(uint8_t *)opaque; 217151e72bc1SEric Blake visit_type_uint8(v, name, &value, errp); 2172e732ea63SMichael S. Tsirkin } 2173e732ea63SMichael S. Tsirkin 2174d7bce999SEric Blake static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, 2175d7bce999SEric Blake void *opaque, Error **errp) 2176e732ea63SMichael S. Tsirkin { 2177e732ea63SMichael S. Tsirkin uint16_t value = *(uint16_t *)opaque; 217851e72bc1SEric Blake visit_type_uint16(v, name, &value, errp); 2179e732ea63SMichael S. Tsirkin } 2180e732ea63SMichael S. Tsirkin 2181d7bce999SEric Blake static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, 2182d7bce999SEric Blake void *opaque, Error **errp) 2183e732ea63SMichael S. Tsirkin { 2184e732ea63SMichael S. Tsirkin uint32_t value = *(uint32_t *)opaque; 218551e72bc1SEric Blake visit_type_uint32(v, name, &value, errp); 2186e732ea63SMichael S. Tsirkin } 2187e732ea63SMichael S. Tsirkin 2188d7bce999SEric Blake static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, 2189d7bce999SEric Blake void *opaque, Error **errp) 2190e732ea63SMichael S. Tsirkin { 2191e732ea63SMichael S. Tsirkin uint64_t value = *(uint64_t *)opaque; 219251e72bc1SEric Blake visit_type_uint64(v, name, &value, errp); 2193e732ea63SMichael S. Tsirkin } 2194e732ea63SMichael S. Tsirkin 2195e732ea63SMichael S. Tsirkin void object_property_add_uint8_ptr(Object *obj, const char *name, 2196e732ea63SMichael S. Tsirkin const uint8_t *v, Error **errp) 2197e732ea63SMichael S. Tsirkin { 2198e732ea63SMichael S. Tsirkin object_property_add(obj, name, "uint8", property_get_uint8_ptr, 2199e732ea63SMichael S. Tsirkin NULL, NULL, (void *)v, errp); 2200e732ea63SMichael S. Tsirkin } 2201e732ea63SMichael S. Tsirkin 220216bf7f52SDaniel P. Berrange void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, 220316bf7f52SDaniel P. Berrange const uint8_t *v, Error **errp) 220416bf7f52SDaniel P. Berrange { 220516bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "uint8", property_get_uint8_ptr, 220616bf7f52SDaniel P. Berrange NULL, NULL, (void *)v, errp); 220716bf7f52SDaniel P. Berrange } 220816bf7f52SDaniel P. Berrange 2209e732ea63SMichael S. Tsirkin void object_property_add_uint16_ptr(Object *obj, const char *name, 2210e732ea63SMichael S. Tsirkin const uint16_t *v, Error **errp) 2211e732ea63SMichael S. Tsirkin { 2212e732ea63SMichael S. Tsirkin object_property_add(obj, name, "uint16", property_get_uint16_ptr, 2213e732ea63SMichael S. Tsirkin NULL, NULL, (void *)v, errp); 2214e732ea63SMichael S. Tsirkin } 2215e732ea63SMichael S. Tsirkin 221616bf7f52SDaniel P. Berrange void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, 221716bf7f52SDaniel P. Berrange const uint16_t *v, Error **errp) 221816bf7f52SDaniel P. Berrange { 221916bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "uint16", property_get_uint16_ptr, 222016bf7f52SDaniel P. Berrange NULL, NULL, (void *)v, errp); 222116bf7f52SDaniel P. Berrange } 222216bf7f52SDaniel P. Berrange 2223e732ea63SMichael S. Tsirkin void object_property_add_uint32_ptr(Object *obj, const char *name, 2224e732ea63SMichael S. Tsirkin const uint32_t *v, Error **errp) 2225e732ea63SMichael S. Tsirkin { 2226e732ea63SMichael S. Tsirkin object_property_add(obj, name, "uint32", property_get_uint32_ptr, 2227e732ea63SMichael S. Tsirkin NULL, NULL, (void *)v, errp); 2228e732ea63SMichael S. Tsirkin } 2229e732ea63SMichael S. Tsirkin 223016bf7f52SDaniel P. Berrange void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, 223116bf7f52SDaniel P. Berrange const uint32_t *v, Error **errp) 223216bf7f52SDaniel P. Berrange { 223316bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "uint32", property_get_uint32_ptr, 223416bf7f52SDaniel P. Berrange NULL, NULL, (void *)v, errp); 223516bf7f52SDaniel P. Berrange } 223616bf7f52SDaniel P. Berrange 2237e732ea63SMichael S. Tsirkin void object_property_add_uint64_ptr(Object *obj, const char *name, 2238e732ea63SMichael S. Tsirkin const uint64_t *v, Error **errp) 2239e732ea63SMichael S. Tsirkin { 2240e732ea63SMichael S. Tsirkin object_property_add(obj, name, "uint64", property_get_uint64_ptr, 2241e732ea63SMichael S. Tsirkin NULL, NULL, (void *)v, errp); 2242e732ea63SMichael S. Tsirkin } 2243e732ea63SMichael S. Tsirkin 224416bf7f52SDaniel P. Berrange void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, 224516bf7f52SDaniel P. Berrange const uint64_t *v, Error **errp) 224616bf7f52SDaniel P. Berrange { 224716bf7f52SDaniel P. Berrange object_class_property_add(klass, name, "uint64", property_get_uint64_ptr, 224816bf7f52SDaniel P. Berrange NULL, NULL, (void *)v, errp); 224916bf7f52SDaniel P. Berrange } 225016bf7f52SDaniel P. Berrange 2251ef7c7ff6SStefan Hajnoczi typedef struct { 2252ef7c7ff6SStefan Hajnoczi Object *target_obj; 22531590d266SEduardo Habkost char *target_name; 2254ef7c7ff6SStefan Hajnoczi } AliasProperty; 2255ef7c7ff6SStefan Hajnoczi 2256d7bce999SEric Blake static void property_get_alias(Object *obj, Visitor *v, const char *name, 2257d7bce999SEric Blake void *opaque, Error **errp) 2258ef7c7ff6SStefan Hajnoczi { 2259ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2260ef7c7ff6SStefan Hajnoczi 2261ef7c7ff6SStefan Hajnoczi object_property_get(prop->target_obj, v, prop->target_name, errp); 2262ef7c7ff6SStefan Hajnoczi } 2263ef7c7ff6SStefan Hajnoczi 2264d7bce999SEric Blake static void property_set_alias(Object *obj, Visitor *v, const char *name, 2265d7bce999SEric Blake void *opaque, Error **errp) 2266ef7c7ff6SStefan Hajnoczi { 2267ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2268ef7c7ff6SStefan Hajnoczi 2269ef7c7ff6SStefan Hajnoczi object_property_set(prop->target_obj, v, prop->target_name, errp); 2270ef7c7ff6SStefan Hajnoczi } 2271ef7c7ff6SStefan Hajnoczi 227264607d08SPaolo Bonzini static Object *property_resolve_alias(Object *obj, void *opaque, 227364607d08SPaolo Bonzini const gchar *part) 227464607d08SPaolo Bonzini { 227564607d08SPaolo Bonzini AliasProperty *prop = opaque; 227664607d08SPaolo Bonzini 227764607d08SPaolo Bonzini return object_resolve_path_component(prop->target_obj, prop->target_name); 227864607d08SPaolo Bonzini } 227964607d08SPaolo Bonzini 2280ef7c7ff6SStefan Hajnoczi static void property_release_alias(Object *obj, const char *name, void *opaque) 2281ef7c7ff6SStefan Hajnoczi { 2282ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2283ef7c7ff6SStefan Hajnoczi 22841590d266SEduardo Habkost g_free(prop->target_name); 2285ef7c7ff6SStefan Hajnoczi g_free(prop); 2286ef7c7ff6SStefan Hajnoczi } 2287ef7c7ff6SStefan Hajnoczi 2288ef7c7ff6SStefan Hajnoczi void object_property_add_alias(Object *obj, const char *name, 2289ef7c7ff6SStefan Hajnoczi Object *target_obj, const char *target_name, 2290ef7c7ff6SStefan Hajnoczi Error **errp) 2291ef7c7ff6SStefan Hajnoczi { 2292ef7c7ff6SStefan Hajnoczi AliasProperty *prop; 229364607d08SPaolo Bonzini ObjectProperty *op; 2294ef7c7ff6SStefan Hajnoczi ObjectProperty *target_prop; 2295d190698eSPaolo Bonzini gchar *prop_type; 22968ae9a9efSGonglei Error *local_err = NULL; 2297ef7c7ff6SStefan Hajnoczi 2298ef7c7ff6SStefan Hajnoczi target_prop = object_property_find(target_obj, target_name, errp); 2299ef7c7ff6SStefan Hajnoczi if (!target_prop) { 2300ef7c7ff6SStefan Hajnoczi return; 2301ef7c7ff6SStefan Hajnoczi } 2302ef7c7ff6SStefan Hajnoczi 2303d190698eSPaolo Bonzini if (object_property_is_child(target_prop)) { 2304d190698eSPaolo Bonzini prop_type = g_strdup_printf("link%s", 2305d190698eSPaolo Bonzini target_prop->type + strlen("child")); 2306d190698eSPaolo Bonzini } else { 2307d190698eSPaolo Bonzini prop_type = g_strdup(target_prop->type); 2308d190698eSPaolo Bonzini } 2309d190698eSPaolo Bonzini 2310ef7c7ff6SStefan Hajnoczi prop = g_malloc(sizeof(*prop)); 2311ef7c7ff6SStefan Hajnoczi prop->target_obj = target_obj; 23121590d266SEduardo Habkost prop->target_name = g_strdup(target_name); 2313ef7c7ff6SStefan Hajnoczi 2314d190698eSPaolo Bonzini op = object_property_add(obj, name, prop_type, 2315ef7c7ff6SStefan Hajnoczi property_get_alias, 2316ef7c7ff6SStefan Hajnoczi property_set_alias, 2317ef7c7ff6SStefan Hajnoczi property_release_alias, 23188ae9a9efSGonglei prop, &local_err); 23198ae9a9efSGonglei if (local_err) { 23208ae9a9efSGonglei error_propagate(errp, local_err); 23218ae9a9efSGonglei g_free(prop); 23228ae9a9efSGonglei goto out; 23238ae9a9efSGonglei } 232464607d08SPaolo Bonzini op->resolve = property_resolve_alias; 2325d190698eSPaolo Bonzini 2326a18bb417SAndreas Färber object_property_set_description(obj, op->name, 232780742642SGonglei target_prop->description, 232880742642SGonglei &error_abort); 232980742642SGonglei 23308ae9a9efSGonglei out: 2331d190698eSPaolo Bonzini g_free(prop_type); 2332ef7c7ff6SStefan Hajnoczi } 2333ef7c7ff6SStefan Hajnoczi 233480742642SGonglei void object_property_set_description(Object *obj, const char *name, 233580742642SGonglei const char *description, Error **errp) 233680742642SGonglei { 233780742642SGonglei ObjectProperty *op; 233880742642SGonglei 233980742642SGonglei op = object_property_find(obj, name, errp); 234080742642SGonglei if (!op) { 234180742642SGonglei return; 234280742642SGonglei } 234380742642SGonglei 234480742642SGonglei g_free(op->description); 234580742642SGonglei op->description = g_strdup(description); 234680742642SGonglei } 234780742642SGonglei 234816bf7f52SDaniel P. Berrange void object_class_property_set_description(ObjectClass *klass, 234916bf7f52SDaniel P. Berrange const char *name, 235016bf7f52SDaniel P. Berrange const char *description, 235116bf7f52SDaniel P. Berrange Error **errp) 235216bf7f52SDaniel P. Berrange { 235316bf7f52SDaniel P. Berrange ObjectProperty *op; 235416bf7f52SDaniel P. Berrange 235516bf7f52SDaniel P. Berrange op = g_hash_table_lookup(klass->properties, name); 235616bf7f52SDaniel P. Berrange if (!op) { 235716bf7f52SDaniel P. Berrange error_setg(errp, "Property '.%s' not found", name); 235816bf7f52SDaniel P. Berrange return; 235916bf7f52SDaniel P. Berrange } 236016bf7f52SDaniel P. Berrange 236116bf7f52SDaniel P. Berrange g_free(op->description); 236216bf7f52SDaniel P. Berrange op->description = g_strdup(description); 236316bf7f52SDaniel P. Berrange } 236416bf7f52SDaniel P. Berrange 23652f262e06SPaolo Bonzini static void object_instance_init(Object *obj) 23662f262e06SPaolo Bonzini { 23672f262e06SPaolo Bonzini object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); 23682f262e06SPaolo Bonzini } 23692f262e06SPaolo Bonzini 2370745549c8SPaolo Bonzini static void register_types(void) 2371745549c8SPaolo Bonzini { 2372745549c8SPaolo Bonzini static TypeInfo interface_info = { 2373745549c8SPaolo Bonzini .name = TYPE_INTERFACE, 237433e95c63SAnthony Liguori .class_size = sizeof(InterfaceClass), 2375745549c8SPaolo Bonzini .abstract = true, 2376745549c8SPaolo Bonzini }; 2377745549c8SPaolo Bonzini 2378745549c8SPaolo Bonzini static TypeInfo object_info = { 2379745549c8SPaolo Bonzini .name = TYPE_OBJECT, 2380745549c8SPaolo Bonzini .instance_size = sizeof(Object), 23812f262e06SPaolo Bonzini .instance_init = object_instance_init, 2382745549c8SPaolo Bonzini .abstract = true, 2383745549c8SPaolo Bonzini }; 2384745549c8SPaolo Bonzini 2385049cb3cfSPaolo Bonzini type_interface = type_register_internal(&interface_info); 2386049cb3cfSPaolo Bonzini type_register_internal(&object_info); 2387745549c8SPaolo Bonzini } 2388745549c8SPaolo Bonzini 2389745549c8SPaolo Bonzini type_init(register_types) 2390