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" 1413d4ff07SMarkus Armbruster #include "hw/qdev-core.h" 15da34e65cSMarkus Armbruster #include "qapi/error.h" 1614cccb61SPaolo Bonzini #include "qom/object.h" 17a31bdae5SDaniel P. Berrange #include "qom/object_interfaces.h" 18f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 197b1b5d19SPaolo Bonzini #include "qapi/visitor.h" 20b2cd7deeSPaolo Bonzini #include "qapi/string-input-visitor.h" 21b2cd7deeSPaolo Bonzini #include "qapi/string-output-visitor.h" 220e76ed0aSMarc-André Lureau #include "qapi/qobject-input-visitor.h" 23eb815e24SMarkus Armbruster #include "qapi/qapi-builtin-visit.h" 247b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h" 250e76ed0aSMarc-André Lureau #include "qapi/qmp/qjson.h" 26fa131d94SPaolo Bonzini #include "trace.h" 272f28d2ffSAnthony Liguori 287b7b7d18SPaolo Bonzini /* TODO: replace QObject with a simpler visitor to avoid a dependency 297b7b7d18SPaolo Bonzini * of the QOM core on QObject? */ 3014cccb61SPaolo Bonzini #include "qom/qom-qobject.h" 317b1b5d19SPaolo Bonzini #include "qapi/qmp/qbool.h" 3215280c36SMarkus Armbruster #include "qapi/qmp/qnum.h" 337b1b5d19SPaolo Bonzini #include "qapi/qmp/qstring.h" 34e02bdf1cSPhilippe Mathieu-Daudé #include "qemu/error-report.h" 357b7b7d18SPaolo Bonzini 362f28d2ffSAnthony Liguori #define MAX_INTERFACES 32 372f28d2ffSAnthony Liguori 382f28d2ffSAnthony Liguori typedef struct InterfaceImpl InterfaceImpl; 392f28d2ffSAnthony Liguori typedef struct TypeImpl TypeImpl; 402f28d2ffSAnthony Liguori 412f28d2ffSAnthony Liguori struct InterfaceImpl 422f28d2ffSAnthony Liguori { 4333e95c63SAnthony Liguori const char *typename; 442f28d2ffSAnthony Liguori }; 452f28d2ffSAnthony Liguori 462f28d2ffSAnthony Liguori struct TypeImpl 472f28d2ffSAnthony Liguori { 482f28d2ffSAnthony Liguori const char *name; 492f28d2ffSAnthony Liguori 502f28d2ffSAnthony Liguori size_t class_size; 512f28d2ffSAnthony Liguori 522f28d2ffSAnthony Liguori size_t instance_size; 532f28d2ffSAnthony Liguori 542f28d2ffSAnthony Liguori void (*class_init)(ObjectClass *klass, void *data); 553b50e311SPaolo Bonzini void (*class_base_init)(ObjectClass *klass, void *data); 562f28d2ffSAnthony Liguori 572f28d2ffSAnthony Liguori void *class_data; 582f28d2ffSAnthony Liguori 592f28d2ffSAnthony Liguori void (*instance_init)(Object *obj); 608231c2ddSEduardo Habkost void (*instance_post_init)(Object *obj); 612f28d2ffSAnthony Liguori void (*instance_finalize)(Object *obj); 622f28d2ffSAnthony Liguori 632f28d2ffSAnthony Liguori bool abstract; 642f28d2ffSAnthony Liguori 652f28d2ffSAnthony Liguori const char *parent; 662f28d2ffSAnthony Liguori TypeImpl *parent_type; 672f28d2ffSAnthony Liguori 682f28d2ffSAnthony Liguori ObjectClass *class; 692f28d2ffSAnthony Liguori 702f28d2ffSAnthony Liguori int num_interfaces; 712f28d2ffSAnthony Liguori InterfaceImpl interfaces[MAX_INTERFACES]; 722f28d2ffSAnthony Liguori }; 732f28d2ffSAnthony Liguori 749970bd88SPaolo Bonzini static Type type_interface; 759970bd88SPaolo Bonzini 762f28d2ffSAnthony Liguori static GHashTable *type_table_get(void) 772f28d2ffSAnthony Liguori { 782f28d2ffSAnthony Liguori static GHashTable *type_table; 792f28d2ffSAnthony Liguori 802f28d2ffSAnthony Liguori if (type_table == NULL) { 812f28d2ffSAnthony Liguori type_table = g_hash_table_new(g_str_hash, g_str_equal); 822f28d2ffSAnthony Liguori } 832f28d2ffSAnthony Liguori 842f28d2ffSAnthony Liguori return type_table; 852f28d2ffSAnthony Liguori } 862f28d2ffSAnthony Liguori 87f54c19caSHervé Poussineau static bool enumerating_types; 88f54c19caSHervé Poussineau 892f28d2ffSAnthony Liguori static void type_table_add(TypeImpl *ti) 902f28d2ffSAnthony Liguori { 91f54c19caSHervé Poussineau assert(!enumerating_types); 922f28d2ffSAnthony Liguori g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 932f28d2ffSAnthony Liguori } 942f28d2ffSAnthony Liguori 952f28d2ffSAnthony Liguori static TypeImpl *type_table_lookup(const char *name) 962f28d2ffSAnthony Liguori { 972f28d2ffSAnthony Liguori return g_hash_table_lookup(type_table_get(), name); 982f28d2ffSAnthony Liguori } 992f28d2ffSAnthony Liguori 100b061dc41SPaolo Bonzini static TypeImpl *type_new(const TypeInfo *info) 1012f28d2ffSAnthony Liguori { 1022f28d2ffSAnthony Liguori TypeImpl *ti = g_malloc0(sizeof(*ti)); 10333e95c63SAnthony Liguori int i; 1042f28d2ffSAnthony Liguori 1052f28d2ffSAnthony Liguori g_assert(info->name != NULL); 1062f28d2ffSAnthony Liguori 10773093354SAnthony Liguori if (type_table_lookup(info->name) != NULL) { 10873093354SAnthony Liguori fprintf(stderr, "Registering `%s' which already exists\n", info->name); 10973093354SAnthony Liguori abort(); 11073093354SAnthony Liguori } 11173093354SAnthony Liguori 1122f28d2ffSAnthony Liguori ti->name = g_strdup(info->name); 1132f28d2ffSAnthony Liguori ti->parent = g_strdup(info->parent); 1142f28d2ffSAnthony Liguori 1152f28d2ffSAnthony Liguori ti->class_size = info->class_size; 1162f28d2ffSAnthony Liguori ti->instance_size = info->instance_size; 1172f28d2ffSAnthony Liguori 1182f28d2ffSAnthony Liguori ti->class_init = info->class_init; 1193b50e311SPaolo Bonzini ti->class_base_init = info->class_base_init; 1202f28d2ffSAnthony Liguori ti->class_data = info->class_data; 1212f28d2ffSAnthony Liguori 1222f28d2ffSAnthony Liguori ti->instance_init = info->instance_init; 1238231c2ddSEduardo Habkost ti->instance_post_init = info->instance_post_init; 1242f28d2ffSAnthony Liguori ti->instance_finalize = info->instance_finalize; 1252f28d2ffSAnthony Liguori 1262f28d2ffSAnthony Liguori ti->abstract = info->abstract; 1272f28d2ffSAnthony Liguori 12833e95c63SAnthony Liguori for (i = 0; info->interfaces && info->interfaces[i].type; i++) { 12933e95c63SAnthony Liguori ti->interfaces[i].typename = g_strdup(info->interfaces[i].type); 1302f28d2ffSAnthony Liguori } 13133e95c63SAnthony Liguori ti->num_interfaces = i; 1322f28d2ffSAnthony Liguori 133b061dc41SPaolo Bonzini return ti; 134b061dc41SPaolo Bonzini } 1352f28d2ffSAnthony Liguori 136b061dc41SPaolo Bonzini static TypeImpl *type_register_internal(const TypeInfo *info) 137b061dc41SPaolo Bonzini { 138b061dc41SPaolo Bonzini TypeImpl *ti; 139b061dc41SPaolo Bonzini ti = type_new(info); 140b061dc41SPaolo Bonzini 141b061dc41SPaolo Bonzini type_table_add(ti); 1422f28d2ffSAnthony Liguori return ti; 1432f28d2ffSAnthony Liguori } 1442f28d2ffSAnthony Liguori 145049cb3cfSPaolo Bonzini TypeImpl *type_register(const TypeInfo *info) 146049cb3cfSPaolo Bonzini { 147049cb3cfSPaolo Bonzini assert(info->parent); 148049cb3cfSPaolo Bonzini return type_register_internal(info); 149049cb3cfSPaolo Bonzini } 150049cb3cfSPaolo Bonzini 1512f28d2ffSAnthony Liguori TypeImpl *type_register_static(const TypeInfo *info) 1522f28d2ffSAnthony Liguori { 1532f28d2ffSAnthony Liguori return type_register(info); 1542f28d2ffSAnthony Liguori } 1552f28d2ffSAnthony Liguori 156aa04c9d2SIgor Mammedov void type_register_static_array(const TypeInfo *infos, int nr_infos) 157aa04c9d2SIgor Mammedov { 158aa04c9d2SIgor Mammedov int i; 159aa04c9d2SIgor Mammedov 160aa04c9d2SIgor Mammedov for (i = 0; i < nr_infos; i++) { 161aa04c9d2SIgor Mammedov type_register_static(&infos[i]); 162aa04c9d2SIgor Mammedov } 163aa04c9d2SIgor Mammedov } 164aa04c9d2SIgor Mammedov 1652f28d2ffSAnthony Liguori static TypeImpl *type_get_by_name(const char *name) 1662f28d2ffSAnthony Liguori { 1672f28d2ffSAnthony Liguori if (name == NULL) { 1682f28d2ffSAnthony Liguori return NULL; 1692f28d2ffSAnthony Liguori } 1702f28d2ffSAnthony Liguori 1712f28d2ffSAnthony Liguori return type_table_lookup(name); 1722f28d2ffSAnthony Liguori } 1732f28d2ffSAnthony Liguori 1742f28d2ffSAnthony Liguori static TypeImpl *type_get_parent(TypeImpl *type) 1752f28d2ffSAnthony Liguori { 1762f28d2ffSAnthony Liguori if (!type->parent_type && type->parent) { 1772f28d2ffSAnthony Liguori type->parent_type = type_get_by_name(type->parent); 17889d337fdSPhilippe Mathieu-Daudé if (!type->parent_type) { 17989d337fdSPhilippe Mathieu-Daudé fprintf(stderr, "Type '%s' is missing its parent '%s'\n", 18089d337fdSPhilippe Mathieu-Daudé type->name, type->parent); 18189d337fdSPhilippe Mathieu-Daudé abort(); 18289d337fdSPhilippe Mathieu-Daudé } 1832f28d2ffSAnthony Liguori } 1842f28d2ffSAnthony Liguori 1852f28d2ffSAnthony Liguori return type->parent_type; 1862f28d2ffSAnthony Liguori } 1872f28d2ffSAnthony Liguori 1882f28d2ffSAnthony Liguori static bool type_has_parent(TypeImpl *type) 1892f28d2ffSAnthony Liguori { 1902f28d2ffSAnthony Liguori return (type->parent != NULL); 1912f28d2ffSAnthony Liguori } 1922f28d2ffSAnthony Liguori 1932f28d2ffSAnthony Liguori static size_t type_class_get_size(TypeImpl *ti) 1942f28d2ffSAnthony Liguori { 1952f28d2ffSAnthony Liguori if (ti->class_size) { 1962f28d2ffSAnthony Liguori return ti->class_size; 1972f28d2ffSAnthony Liguori } 1982f28d2ffSAnthony Liguori 1992f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 2002f28d2ffSAnthony Liguori return type_class_get_size(type_get_parent(ti)); 2012f28d2ffSAnthony Liguori } 2022f28d2ffSAnthony Liguori 2032f28d2ffSAnthony Liguori return sizeof(ObjectClass); 2042f28d2ffSAnthony Liguori } 2052f28d2ffSAnthony Liguori 206aca59af6SIgor Mitsyanko static size_t type_object_get_size(TypeImpl *ti) 207aca59af6SIgor Mitsyanko { 208aca59af6SIgor Mitsyanko if (ti->instance_size) { 209aca59af6SIgor Mitsyanko return ti->instance_size; 210aca59af6SIgor Mitsyanko } 211aca59af6SIgor Mitsyanko 212aca59af6SIgor Mitsyanko if (type_has_parent(ti)) { 213aca59af6SIgor Mitsyanko return type_object_get_size(type_get_parent(ti)); 214aca59af6SIgor Mitsyanko } 215aca59af6SIgor Mitsyanko 216aca59af6SIgor Mitsyanko return 0; 217aca59af6SIgor Mitsyanko } 218aca59af6SIgor Mitsyanko 2193f97b53aSBharata B Rao size_t object_type_get_instance_size(const char *typename) 2203f97b53aSBharata B Rao { 2213f97b53aSBharata B Rao TypeImpl *type = type_get_by_name(typename); 2223f97b53aSBharata B Rao 2233f97b53aSBharata B Rao g_assert(type != NULL); 2243f97b53aSBharata B Rao return type_object_get_size(type); 2253f97b53aSBharata B Rao } 2263f97b53aSBharata B Rao 22733e95c63SAnthony Liguori static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 2282f28d2ffSAnthony Liguori { 22933e95c63SAnthony Liguori assert(target_type); 2302f28d2ffSAnthony Liguori 231b30d8054SCao jin /* Check if target_type is a direct ancestor of type */ 23233e95c63SAnthony Liguori while (type) { 23333e95c63SAnthony Liguori if (type == target_type) { 23433e95c63SAnthony Liguori return true; 23533e95c63SAnthony Liguori } 23633e95c63SAnthony Liguori 23733e95c63SAnthony Liguori type = type_get_parent(type); 23833e95c63SAnthony Liguori } 23933e95c63SAnthony Liguori 24033e95c63SAnthony Liguori return false; 24133e95c63SAnthony Liguori } 24233e95c63SAnthony Liguori 24333e95c63SAnthony Liguori static void type_initialize(TypeImpl *ti); 24433e95c63SAnthony Liguori 245b061dc41SPaolo Bonzini static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, 246b061dc41SPaolo Bonzini TypeImpl *parent_type) 24733e95c63SAnthony Liguori { 24833e95c63SAnthony Liguori InterfaceClass *new_iface; 24933e95c63SAnthony Liguori TypeInfo info = { }; 25033e95c63SAnthony Liguori TypeImpl *iface_impl; 25133e95c63SAnthony Liguori 252b061dc41SPaolo Bonzini info.parent = parent_type->name; 253b061dc41SPaolo Bonzini info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name); 25433e95c63SAnthony Liguori info.abstract = true; 25533e95c63SAnthony Liguori 256b061dc41SPaolo Bonzini iface_impl = type_new(&info); 257b061dc41SPaolo Bonzini iface_impl->parent_type = parent_type; 25833e95c63SAnthony Liguori type_initialize(iface_impl); 25933e95c63SAnthony Liguori g_free((char *)info.name); 26033e95c63SAnthony Liguori 26133e95c63SAnthony Liguori new_iface = (InterfaceClass *)iface_impl->class; 26233e95c63SAnthony Liguori new_iface->concrete_class = ti->class; 263b061dc41SPaolo Bonzini new_iface->interface_type = interface_type; 26433e95c63SAnthony Liguori 2653d91293eSMasahiro Yamada ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface); 2662f28d2ffSAnthony Liguori } 2672f28d2ffSAnthony Liguori 26816bf7f52SDaniel P. Berrange static void object_property_free(gpointer data) 26916bf7f52SDaniel P. Berrange { 27016bf7f52SDaniel P. Berrange ObjectProperty *prop = data; 27116bf7f52SDaniel P. Berrange 2720e76ed0aSMarc-André Lureau if (prop->defval) { 2730e76ed0aSMarc-André Lureau qobject_unref(prop->defval); 2740e76ed0aSMarc-André Lureau prop->defval = NULL; 2750e76ed0aSMarc-André Lureau } 27616bf7f52SDaniel P. Berrange g_free(prop->name); 27716bf7f52SDaniel P. Berrange g_free(prop->type); 27816bf7f52SDaniel P. Berrange g_free(prop->description); 27916bf7f52SDaniel P. Berrange g_free(prop); 28016bf7f52SDaniel P. Berrange } 28116bf7f52SDaniel P. Berrange 282ac451033SIgor Mitsyanko static void type_initialize(TypeImpl *ti) 2832f28d2ffSAnthony Liguori { 284745549c8SPaolo Bonzini TypeImpl *parent; 2852f28d2ffSAnthony Liguori 2862f28d2ffSAnthony Liguori if (ti->class) { 2872f28d2ffSAnthony Liguori return; 2882f28d2ffSAnthony Liguori } 2892f28d2ffSAnthony Liguori 2902f28d2ffSAnthony Liguori ti->class_size = type_class_get_size(ti); 291aca59af6SIgor Mitsyanko ti->instance_size = type_object_get_size(ti); 2921c6d75d5SEduardo Habkost /* Any type with zero instance_size is implicitly abstract. 2931c6d75d5SEduardo Habkost * This means interface types are all abstract. 2941c6d75d5SEduardo Habkost */ 2951c6d75d5SEduardo Habkost if (ti->instance_size == 0) { 2961c6d75d5SEduardo Habkost ti->abstract = true; 2971c6d75d5SEduardo Habkost } 298422ca143SMarc-André Lureau if (type_is_ancestor(ti, type_interface)) { 299422ca143SMarc-André Lureau assert(ti->instance_size == 0); 300422ca143SMarc-André Lureau assert(ti->abstract); 301422ca143SMarc-André Lureau assert(!ti->instance_init); 302422ca143SMarc-André Lureau assert(!ti->instance_post_init); 303422ca143SMarc-André Lureau assert(!ti->instance_finalize); 304422ca143SMarc-André Lureau assert(!ti->num_interfaces); 305422ca143SMarc-André Lureau } 3062f28d2ffSAnthony Liguori ti->class = g_malloc0(ti->class_size); 3072f28d2ffSAnthony Liguori 308745549c8SPaolo Bonzini parent = type_get_parent(ti); 309745549c8SPaolo Bonzini if (parent) { 310ac451033SIgor Mitsyanko type_initialize(parent); 31133e95c63SAnthony Liguori GSList *e; 31233e95c63SAnthony Liguori int i; 3132f28d2ffSAnthony Liguori 314719a3077SMarkus Armbruster g_assert(parent->class_size <= ti->class_size); 315d5e633fcSMarc-André Lureau g_assert(parent->instance_size <= ti->instance_size); 316745549c8SPaolo Bonzini memcpy(ti->class, parent->class, parent->class_size); 3173e407de4SPeter Crosthwaite ti->class->interfaces = NULL; 31833e95c63SAnthony Liguori 31933e95c63SAnthony Liguori for (e = parent->class->interfaces; e; e = e->next) { 320b061dc41SPaolo Bonzini InterfaceClass *iface = e->data; 321b061dc41SPaolo Bonzini ObjectClass *klass = OBJECT_CLASS(iface); 322b061dc41SPaolo Bonzini 323b061dc41SPaolo Bonzini type_initialize_interface(ti, iface->interface_type, klass->type); 32433e95c63SAnthony Liguori } 32533e95c63SAnthony Liguori 32633e95c63SAnthony Liguori for (i = 0; i < ti->num_interfaces; i++) { 32733e95c63SAnthony Liguori TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); 328a9ee3a9eSPhilippe Mathieu-Daudé if (!t) { 329a9ee3a9eSPhilippe Mathieu-Daudé error_report("missing interface '%s' for object '%s'", 330a9ee3a9eSPhilippe Mathieu-Daudé ti->interfaces[i].typename, parent->name); 331a9ee3a9eSPhilippe Mathieu-Daudé abort(); 332a9ee3a9eSPhilippe Mathieu-Daudé } 33333e95c63SAnthony Liguori for (e = ti->class->interfaces; e; e = e->next) { 33433e95c63SAnthony Liguori TypeImpl *target_type = OBJECT_CLASS(e->data)->type; 33533e95c63SAnthony Liguori 33633e95c63SAnthony Liguori if (type_is_ancestor(target_type, t)) { 33733e95c63SAnthony Liguori break; 33833e95c63SAnthony Liguori } 33933e95c63SAnthony Liguori } 34033e95c63SAnthony Liguori 34133e95c63SAnthony Liguori if (e) { 34233e95c63SAnthony Liguori continue; 34333e95c63SAnthony Liguori } 34433e95c63SAnthony Liguori 345b061dc41SPaolo Bonzini type_initialize_interface(ti, t, t); 34633e95c63SAnthony Liguori } 347745549c8SPaolo Bonzini } 3482f28d2ffSAnthony Liguori 349e5a0cc5eSMasahiro Yamada ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, 350e5a0cc5eSMasahiro Yamada object_property_free); 351e5a0cc5eSMasahiro Yamada 352745549c8SPaolo Bonzini ti->class->type = ti; 3533b50e311SPaolo Bonzini 3543b50e311SPaolo Bonzini while (parent) { 3553b50e311SPaolo Bonzini if (parent->class_base_init) { 3563b50e311SPaolo Bonzini parent->class_base_init(ti->class, ti->class_data); 3573b50e311SPaolo Bonzini } 3583b50e311SPaolo Bonzini parent = type_get_parent(parent); 3593b50e311SPaolo Bonzini } 3602f28d2ffSAnthony Liguori 3612f28d2ffSAnthony Liguori if (ti->class_init) { 3622f28d2ffSAnthony Liguori ti->class_init(ti->class, ti->class_data); 3632f28d2ffSAnthony Liguori } 3642f28d2ffSAnthony Liguori } 3652f28d2ffSAnthony Liguori 3662f28d2ffSAnthony Liguori static void object_init_with_type(Object *obj, TypeImpl *ti) 3672f28d2ffSAnthony Liguori { 3682f28d2ffSAnthony Liguori if (type_has_parent(ti)) { 3692f28d2ffSAnthony Liguori object_init_with_type(obj, type_get_parent(ti)); 3702f28d2ffSAnthony Liguori } 3712f28d2ffSAnthony Liguori 3722f28d2ffSAnthony Liguori if (ti->instance_init) { 3732f28d2ffSAnthony Liguori ti->instance_init(obj); 3742f28d2ffSAnthony Liguori } 3752f28d2ffSAnthony Liguori } 3762f28d2ffSAnthony Liguori 3778231c2ddSEduardo Habkost static void object_post_init_with_type(Object *obj, TypeImpl *ti) 3788231c2ddSEduardo Habkost { 3798231c2ddSEduardo Habkost if (ti->instance_post_init) { 3808231c2ddSEduardo Habkost ti->instance_post_init(obj); 3818231c2ddSEduardo Habkost } 3828231c2ddSEduardo Habkost 3838231c2ddSEduardo Habkost if (type_has_parent(ti)) { 3848231c2ddSEduardo Habkost object_post_init_with_type(obj, type_get_parent(ti)); 3858231c2ddSEduardo Habkost } 3868231c2ddSEduardo Habkost } 3878231c2ddSEduardo Habkost 388ea9ce893SMarc-André Lureau void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp) 389ea9ce893SMarc-André Lureau { 390ea9ce893SMarc-André Lureau int i; 391ea9ce893SMarc-André Lureau 392ea9ce893SMarc-André Lureau if (!props) { 393ea9ce893SMarc-André Lureau return; 394ea9ce893SMarc-André Lureau } 395ea9ce893SMarc-André Lureau 396ea9ce893SMarc-André Lureau for (i = 0; i < props->len; i++) { 397ea9ce893SMarc-André Lureau GlobalProperty *p = g_ptr_array_index(props, i); 398d769f0dfSEduardo Habkost Error *err = NULL; 399ea9ce893SMarc-André Lureau 400ea9ce893SMarc-André Lureau if (object_dynamic_cast(obj, p->driver) == NULL) { 401ea9ce893SMarc-André Lureau continue; 402ea9ce893SMarc-André Lureau } 40392fd453cSDr. David Alan Gilbert if (p->optional && !object_property_find(obj, p->property, NULL)) { 40492fd453cSDr. David Alan Gilbert continue; 40592fd453cSDr. David Alan Gilbert } 406ea9ce893SMarc-André Lureau p->used = true; 407ea9ce893SMarc-André Lureau object_property_parse(obj, p->value, p->property, &err); 408ea9ce893SMarc-André Lureau if (err != NULL) { 409ea9ce893SMarc-André Lureau error_prepend(&err, "can't apply global %s.%s=%s: ", 410ea9ce893SMarc-André Lureau p->driver, p->property, p->value); 41150545b2cSMarc-André Lureau /* 41250545b2cSMarc-André Lureau * If errp != NULL, propagate error and return. 41350545b2cSMarc-André Lureau * If errp == NULL, report a warning, but keep going 41450545b2cSMarc-André Lureau * with the remaining globals. 41550545b2cSMarc-André Lureau */ 41650545b2cSMarc-André Lureau if (errp) { 417ea9ce893SMarc-André Lureau error_propagate(errp, err); 41850545b2cSMarc-André Lureau return; 41950545b2cSMarc-André Lureau } else { 42050545b2cSMarc-André Lureau warn_report_err(err); 42150545b2cSMarc-André Lureau } 422ea9ce893SMarc-André Lureau } 423ea9ce893SMarc-André Lureau } 424ea9ce893SMarc-André Lureau } 425ea9ce893SMarc-André Lureau 426617902afSMarkus Armbruster /* 427617902afSMarkus Armbruster * Global property defaults 428617902afSMarkus Armbruster * Slot 0: accelerator's global property defaults 429617902afSMarkus Armbruster * Slot 1: machine's global property defaults 4301fff3c20SPaolo Bonzini * Slot 2: global properties from legacy command line option 431617902afSMarkus Armbruster * Each is a GPtrArray of of GlobalProperty. 432617902afSMarkus Armbruster * Applied in order, later entries override earlier ones. 433617902afSMarkus Armbruster */ 4341fff3c20SPaolo Bonzini static GPtrArray *object_compat_props[3]; 4351fff3c20SPaolo Bonzini 4361fff3c20SPaolo Bonzini /* 4371fff3c20SPaolo Bonzini * Retrieve @GPtrArray for global property defined with options 4381fff3c20SPaolo Bonzini * other than "-global". These are generally used for syntactic 4391fff3c20SPaolo Bonzini * sugar and legacy command line options. 4401fff3c20SPaolo Bonzini */ 4411fff3c20SPaolo Bonzini void object_register_sugar_prop(const char *driver, const char *prop, const char *value) 4421fff3c20SPaolo Bonzini { 4431fff3c20SPaolo Bonzini GlobalProperty *g; 4441fff3c20SPaolo Bonzini if (!object_compat_props[2]) { 4451fff3c20SPaolo Bonzini object_compat_props[2] = g_ptr_array_new(); 4461fff3c20SPaolo Bonzini } 4471fff3c20SPaolo Bonzini g = g_new0(GlobalProperty, 1); 4481fff3c20SPaolo Bonzini g->driver = g_strdup(driver); 4491fff3c20SPaolo Bonzini g->property = g_strdup(prop); 4501fff3c20SPaolo Bonzini g->value = g_strdup(value); 4511fff3c20SPaolo Bonzini g_ptr_array_add(object_compat_props[2], g); 4521fff3c20SPaolo Bonzini } 453617902afSMarkus Armbruster 454617902afSMarkus Armbruster /* 455617902afSMarkus Armbruster * Set machine's global property defaults to @compat_props. 456617902afSMarkus Armbruster * May be called at most once. 457617902afSMarkus Armbruster */ 458617902afSMarkus Armbruster void object_set_machine_compat_props(GPtrArray *compat_props) 459617902afSMarkus Armbruster { 460617902afSMarkus Armbruster assert(!object_compat_props[1]); 461617902afSMarkus Armbruster object_compat_props[1] = compat_props; 462617902afSMarkus Armbruster } 463617902afSMarkus Armbruster 464617902afSMarkus Armbruster /* 465617902afSMarkus Armbruster * Set accelerator's global property defaults to @compat_props. 466617902afSMarkus Armbruster * May be called at most once. 467617902afSMarkus Armbruster */ 468617902afSMarkus Armbruster void object_set_accelerator_compat_props(GPtrArray *compat_props) 469617902afSMarkus Armbruster { 470617902afSMarkus Armbruster assert(!object_compat_props[0]); 471617902afSMarkus Armbruster object_compat_props[0] = compat_props; 472617902afSMarkus Armbruster } 473617902afSMarkus Armbruster 474617902afSMarkus Armbruster void object_apply_compat_props(Object *obj) 475617902afSMarkus Armbruster { 476617902afSMarkus Armbruster int i; 477617902afSMarkus Armbruster 478617902afSMarkus Armbruster for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) { 479617902afSMarkus Armbruster object_apply_global_props(obj, object_compat_props[i], 4801fff3c20SPaolo Bonzini i == 2 ? &error_fatal : &error_abort); 481617902afSMarkus Armbruster } 482617902afSMarkus Armbruster } 483617902afSMarkus Armbruster 4842a1be4b3SMarc-André Lureau static void object_class_property_init_all(Object *obj) 4852a1be4b3SMarc-André Lureau { 4862a1be4b3SMarc-André Lureau ObjectPropertyIterator iter; 4872a1be4b3SMarc-André Lureau ObjectProperty *prop; 4882a1be4b3SMarc-André Lureau 4892a1be4b3SMarc-André Lureau object_class_property_iter_init(&iter, object_get_class(obj)); 4902a1be4b3SMarc-André Lureau while ((prop = object_property_iter_next(&iter))) { 4912a1be4b3SMarc-André Lureau if (prop->init) { 4922a1be4b3SMarc-André Lureau prop->init(obj, prop); 4932a1be4b3SMarc-André Lureau } 4942a1be4b3SMarc-André Lureau } 4952a1be4b3SMarc-André Lureau } 4962a1be4b3SMarc-André Lureau 497e27a9595SMasahiro Yamada static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type) 4982f28d2ffSAnthony Liguori { 499ac451033SIgor Mitsyanko type_initialize(type); 500aca59af6SIgor Mitsyanko 501719a3077SMarkus Armbruster g_assert(type->instance_size >= sizeof(Object)); 5022f28d2ffSAnthony Liguori g_assert(type->abstract == false); 503719a3077SMarkus Armbruster g_assert(size >= type->instance_size); 5042f28d2ffSAnthony Liguori 5052f28d2ffSAnthony Liguori memset(obj, 0, type->instance_size); 5062f28d2ffSAnthony Liguori obj->class = type->class; 507764b6312SPaolo Bonzini object_ref(obj); 5082a1be4b3SMarc-André Lureau object_class_property_init_all(obj); 509b604a854SPavel Fedin obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, 510b604a854SPavel Fedin NULL, object_property_free); 5112f28d2ffSAnthony Liguori object_init_with_type(obj, type); 5128231c2ddSEduardo Habkost object_post_init_with_type(obj, type); 5132f28d2ffSAnthony Liguori } 5142f28d2ffSAnthony Liguori 515213f0c4fSAndreas Färber void object_initialize(void *data, size_t size, const char *typename) 5162f28d2ffSAnthony Liguori { 5172f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 5182f28d2ffSAnthony Liguori 519e02bdf1cSPhilippe Mathieu-Daudé if (!type) { 520e02bdf1cSPhilippe Mathieu-Daudé error_report("missing object type '%s'", typename); 521e02bdf1cSPhilippe Mathieu-Daudé abort(); 522e02bdf1cSPhilippe Mathieu-Daudé } 523e02bdf1cSPhilippe Mathieu-Daudé 5245b9237f6SAndreas Färber object_initialize_with_type(data, size, type); 5252f28d2ffSAnthony Liguori } 5262f28d2ffSAnthony Liguori 5279fc7fc4dSMarkus Armbruster void object_initialize_child_with_props(Object *parentobj, 5289fc7fc4dSMarkus Armbruster const char *propname, 5290210b39dSThomas Huth void *childobj, size_t size, const char *type, 5300210b39dSThomas Huth Error **errp, ...) 5310210b39dSThomas Huth { 5320210b39dSThomas Huth va_list vargs; 5330210b39dSThomas Huth 5340210b39dSThomas Huth va_start(vargs, errp); 5359fc7fc4dSMarkus Armbruster object_initialize_child_with_propsv(parentobj, propname, 5369fc7fc4dSMarkus Armbruster childobj, size, type, errp, vargs); 5370210b39dSThomas Huth va_end(vargs); 5380210b39dSThomas Huth } 5390210b39dSThomas Huth 5409fc7fc4dSMarkus Armbruster void object_initialize_child_with_propsv(Object *parentobj, 5419fc7fc4dSMarkus Armbruster const char *propname, 5420210b39dSThomas Huth void *childobj, size_t size, const char *type, 5430210b39dSThomas Huth Error **errp, va_list vargs) 5440210b39dSThomas Huth { 5450210b39dSThomas Huth Error *local_err = NULL; 5460210b39dSThomas Huth Object *obj; 5473650b2deSMarc-André Lureau UserCreatable *uc; 5480210b39dSThomas Huth 5490210b39dSThomas Huth object_initialize(childobj, size, type); 5500210b39dSThomas Huth obj = OBJECT(childobj); 5510210b39dSThomas Huth 5520210b39dSThomas Huth object_set_propv(obj, &local_err, vargs); 5530210b39dSThomas Huth if (local_err) { 5540210b39dSThomas Huth goto out; 5550210b39dSThomas Huth } 5560210b39dSThomas Huth 557d2623129SMarkus Armbruster object_property_add_child(parentobj, propname, obj); 5580210b39dSThomas Huth 5593650b2deSMarc-André Lureau uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); 5603650b2deSMarc-André Lureau if (uc) { 5613650b2deSMarc-André Lureau user_creatable_complete(uc, &local_err); 5620210b39dSThomas Huth if (local_err) { 5630210b39dSThomas Huth object_unparent(obj); 5640210b39dSThomas Huth goto out; 5650210b39dSThomas Huth } 5660210b39dSThomas Huth } 5670210b39dSThomas Huth 568975ac455SMarkus Armbruster out: 5690210b39dSThomas Huth /* 570975ac455SMarkus Armbruster * We want @obj's reference to be 1 on success, 0 on failure. 571975ac455SMarkus Armbruster * On success, it's 2: one taken by object_initialize(), and one 572975ac455SMarkus Armbruster * by object_property_add_child(). 573975ac455SMarkus Armbruster * On failure in object_initialize() or earlier, it's 1. 574975ac455SMarkus Armbruster * On failure afterwards, it's also 1: object_unparent() releases 575975ac455SMarkus Armbruster * the reference taken by object_property_add_child(). 5760210b39dSThomas Huth */ 5770210b39dSThomas Huth object_unref(obj); 5780210b39dSThomas Huth 5790210b39dSThomas Huth error_propagate(errp, local_err); 5800210b39dSThomas Huth } 5810210b39dSThomas Huth 5829fc7fc4dSMarkus Armbruster void object_initialize_child_internal(Object *parent, 5839fc7fc4dSMarkus Armbruster const char *propname, 5849fc7fc4dSMarkus Armbruster void *child, size_t size, 5859fc7fc4dSMarkus Armbruster const char *type) 5869fc7fc4dSMarkus Armbruster { 5879fc7fc4dSMarkus Armbruster object_initialize_child_with_props(parent, propname, child, size, type, 5889fc7fc4dSMarkus Armbruster &error_abort, NULL); 5899fc7fc4dSMarkus Armbruster } 5909fc7fc4dSMarkus Armbruster 5915d9d3f47SAndreas Färber static inline bool object_property_is_child(ObjectProperty *prop) 5925d9d3f47SAndreas Färber { 5935d9d3f47SAndreas Färber return strstart(prop->type, "child<", NULL); 5945d9d3f47SAndreas Färber } 5955d9d3f47SAndreas Färber 59657c9fafeSAnthony Liguori static void object_property_del_all(Object *obj) 59757c9fafeSAnthony Liguori { 5989859faccSMarc-André Lureau g_autoptr(GHashTable) done = g_hash_table_new(NULL, NULL); 599b604a854SPavel Fedin ObjectProperty *prop; 6009859faccSMarc-André Lureau ObjectPropertyIterator iter; 601b604a854SPavel Fedin bool released; 60257c9fafeSAnthony Liguori 603b604a854SPavel Fedin do { 604b604a854SPavel Fedin released = false; 6059859faccSMarc-André Lureau object_property_iter_init(&iter, obj); 6069859faccSMarc-André Lureau while ((prop = object_property_iter_next(&iter)) != NULL) { 6079859faccSMarc-André Lureau if (g_hash_table_add(done, prop)) { 60857c9fafeSAnthony Liguori if (prop->release) { 60957c9fafeSAnthony Liguori prop->release(obj, prop->name, prop->opaque); 610b604a854SPavel Fedin released = true; 611b604a854SPavel Fedin break; 61257c9fafeSAnthony Liguori } 6139859faccSMarc-André Lureau } 614b604a854SPavel Fedin } 615b604a854SPavel Fedin } while (released); 61657c9fafeSAnthony Liguori 617b604a854SPavel Fedin g_hash_table_unref(obj->properties); 61857c9fafeSAnthony Liguori } 61957c9fafeSAnthony Liguori 620f73a32a5SMarkus Armbruster static void object_property_del_child(Object *obj, Object *child) 62157c9fafeSAnthony Liguori { 62257c9fafeSAnthony Liguori ObjectProperty *prop; 623b604a854SPavel Fedin GHashTableIter iter; 624b604a854SPavel Fedin gpointer key, value; 62557c9fafeSAnthony Liguori 626b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 627b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) { 628b604a854SPavel Fedin prop = value; 6295d9d3f47SAndreas Färber if (object_property_is_child(prop) && prop->opaque == child) { 630b604a854SPavel Fedin if (prop->release) { 631b604a854SPavel Fedin prop->release(obj, prop->name, prop->opaque); 632b604a854SPavel Fedin prop->release = NULL; 633b604a854SPavel Fedin } 634b604a854SPavel Fedin break; 635b604a854SPavel Fedin } 636b604a854SPavel Fedin } 637b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 638b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) { 639b604a854SPavel Fedin prop = value; 640b604a854SPavel Fedin if (object_property_is_child(prop) && prop->opaque == child) { 641b604a854SPavel Fedin g_hash_table_iter_remove(&iter); 6426c1fdcf9SPaolo Bonzini break; 64357c9fafeSAnthony Liguori } 64457c9fafeSAnthony Liguori } 64557c9fafeSAnthony Liguori } 64657c9fafeSAnthony Liguori 64757c9fafeSAnthony Liguori void object_unparent(Object *obj) 64857c9fafeSAnthony Liguori { 649e998fa8dSMichael S. Tsirkin if (obj->parent) { 650f73a32a5SMarkus Armbruster object_property_del_child(obj->parent, obj); 651e998fa8dSMichael S. Tsirkin } 65257c9fafeSAnthony Liguori } 65357c9fafeSAnthony Liguori 6542f28d2ffSAnthony Liguori static void object_deinit(Object *obj, TypeImpl *type) 6552f28d2ffSAnthony Liguori { 6562f28d2ffSAnthony Liguori if (type->instance_finalize) { 6572f28d2ffSAnthony Liguori type->instance_finalize(obj); 6582f28d2ffSAnthony Liguori } 6592f28d2ffSAnthony Liguori 6602f28d2ffSAnthony Liguori if (type_has_parent(type)) { 6612f28d2ffSAnthony Liguori object_deinit(obj, type_get_parent(type)); 6622f28d2ffSAnthony Liguori } 6632f28d2ffSAnthony Liguori } 6642f28d2ffSAnthony Liguori 665339c2708SPaolo Bonzini static void object_finalize(void *data) 6662f28d2ffSAnthony Liguori { 6672f28d2ffSAnthony Liguori Object *obj = data; 6682f28d2ffSAnthony Liguori TypeImpl *ti = obj->class->type; 6692f28d2ffSAnthony Liguori 67057c9fafeSAnthony Liguori object_property_del_all(obj); 67176a6e1ccSPaolo Bonzini object_deinit(obj, ti); 672db85b575SAnthony Liguori 673719a3077SMarkus Armbruster g_assert(obj->ref == 0); 674fde9bf44SPaolo Bonzini if (obj->free) { 675fde9bf44SPaolo Bonzini obj->free(obj); 676fde9bf44SPaolo Bonzini } 6772f28d2ffSAnthony Liguori } 6782f28d2ffSAnthony Liguori 67963f7b10bSMarc-André Lureau static Object *object_new_with_type(Type type) 6802f28d2ffSAnthony Liguori { 6812f28d2ffSAnthony Liguori Object *obj; 6822f28d2ffSAnthony Liguori 6832f28d2ffSAnthony Liguori g_assert(type != NULL); 684ac451033SIgor Mitsyanko type_initialize(type); 6852f28d2ffSAnthony Liguori 6862f28d2ffSAnthony Liguori obj = g_malloc(type->instance_size); 6875b9237f6SAndreas Färber object_initialize_with_type(obj, type->instance_size, type); 688fde9bf44SPaolo Bonzini obj->free = g_free; 6892f28d2ffSAnthony Liguori 6902f28d2ffSAnthony Liguori return obj; 6912f28d2ffSAnthony Liguori } 6922f28d2ffSAnthony Liguori 6933c75e12eSPaolo Bonzini Object *object_new_with_class(ObjectClass *klass) 6943c75e12eSPaolo Bonzini { 6953c75e12eSPaolo Bonzini return object_new_with_type(klass->type); 6963c75e12eSPaolo Bonzini } 6973c75e12eSPaolo Bonzini 6982f28d2ffSAnthony Liguori Object *object_new(const char *typename) 6992f28d2ffSAnthony Liguori { 7002f28d2ffSAnthony Liguori TypeImpl *ti = type_get_by_name(typename); 7012f28d2ffSAnthony Liguori 7022f28d2ffSAnthony Liguori return object_new_with_type(ti); 7032f28d2ffSAnthony Liguori } 7042f28d2ffSAnthony Liguori 705a31bdae5SDaniel P. Berrange 706a31bdae5SDaniel P. Berrange Object *object_new_with_props(const char *typename, 707a31bdae5SDaniel P. Berrange Object *parent, 708a31bdae5SDaniel P. Berrange const char *id, 709a31bdae5SDaniel P. Berrange Error **errp, 710a31bdae5SDaniel P. Berrange ...) 711a31bdae5SDaniel P. Berrange { 712a31bdae5SDaniel P. Berrange va_list vargs; 713a31bdae5SDaniel P. Berrange Object *obj; 714a31bdae5SDaniel P. Berrange 715a31bdae5SDaniel P. Berrange va_start(vargs, errp); 716a31bdae5SDaniel P. Berrange obj = object_new_with_propv(typename, parent, id, errp, vargs); 717a31bdae5SDaniel P. Berrange va_end(vargs); 718a31bdae5SDaniel P. Berrange 719a31bdae5SDaniel P. Berrange return obj; 720a31bdae5SDaniel P. Berrange } 721a31bdae5SDaniel P. Berrange 722a31bdae5SDaniel P. Berrange 723a31bdae5SDaniel P. Berrange Object *object_new_with_propv(const char *typename, 724a31bdae5SDaniel P. Berrange Object *parent, 725a31bdae5SDaniel P. Berrange const char *id, 726a31bdae5SDaniel P. Berrange Error **errp, 727a31bdae5SDaniel P. Berrange va_list vargs) 728a31bdae5SDaniel P. Berrange { 729a31bdae5SDaniel P. Berrange Object *obj; 730a31bdae5SDaniel P. Berrange ObjectClass *klass; 731a31bdae5SDaniel P. Berrange Error *local_err = NULL; 7323650b2deSMarc-André Lureau UserCreatable *uc; 733a31bdae5SDaniel P. Berrange 734a31bdae5SDaniel P. Berrange klass = object_class_by_name(typename); 735a31bdae5SDaniel P. Berrange if (!klass) { 736a31bdae5SDaniel P. Berrange error_setg(errp, "invalid object type: %s", typename); 737a31bdae5SDaniel P. Berrange return NULL; 738a31bdae5SDaniel P. Berrange } 739a31bdae5SDaniel P. Berrange 740a31bdae5SDaniel P. Berrange if (object_class_is_abstract(klass)) { 741a31bdae5SDaniel P. Berrange error_setg(errp, "object type '%s' is abstract", typename); 742a31bdae5SDaniel P. Berrange return NULL; 743a31bdae5SDaniel P. Berrange } 74466e1155aSWei Yang obj = object_new_with_type(klass->type); 745a31bdae5SDaniel P. Berrange 746a31bdae5SDaniel P. Berrange if (object_set_propv(obj, &local_err, vargs) < 0) { 747a31bdae5SDaniel P. Berrange goto error; 748a31bdae5SDaniel P. Berrange } 749a31bdae5SDaniel P. Berrange 7506134d752SDaniel P. Berrangé if (id != NULL) { 751d2623129SMarkus Armbruster object_property_add_child(parent, id, obj); 7526134d752SDaniel P. Berrangé } 753a31bdae5SDaniel P. Berrange 7543650b2deSMarc-André Lureau uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); 7553650b2deSMarc-André Lureau if (uc) { 7563650b2deSMarc-André Lureau user_creatable_complete(uc, &local_err); 757a31bdae5SDaniel P. Berrange if (local_err) { 7586134d752SDaniel P. Berrangé if (id != NULL) { 759a31bdae5SDaniel P. Berrange object_unparent(obj); 7606134d752SDaniel P. Berrangé } 761a31bdae5SDaniel P. Berrange goto error; 762a31bdae5SDaniel P. Berrange } 763a31bdae5SDaniel P. Berrange } 764a31bdae5SDaniel P. Berrange 765688ffbb4SPhilippe Mathieu-Daudé object_unref(obj); 766a31bdae5SDaniel P. Berrange return obj; 767a31bdae5SDaniel P. Berrange 768a31bdae5SDaniel P. Berrange error: 769a31bdae5SDaniel P. Berrange error_propagate(errp, local_err); 770a31bdae5SDaniel P. Berrange object_unref(obj); 771a31bdae5SDaniel P. Berrange return NULL; 772a31bdae5SDaniel P. Berrange } 773a31bdae5SDaniel P. Berrange 774a31bdae5SDaniel P. Berrange 775a31bdae5SDaniel P. Berrange int object_set_props(Object *obj, 776a31bdae5SDaniel P. Berrange Error **errp, 777a31bdae5SDaniel P. Berrange ...) 778a31bdae5SDaniel P. Berrange { 779a31bdae5SDaniel P. Berrange va_list vargs; 780a31bdae5SDaniel P. Berrange int ret; 781a31bdae5SDaniel P. Berrange 782a31bdae5SDaniel P. Berrange va_start(vargs, errp); 783a31bdae5SDaniel P. Berrange ret = object_set_propv(obj, errp, vargs); 784a31bdae5SDaniel P. Berrange va_end(vargs); 785a31bdae5SDaniel P. Berrange 786a31bdae5SDaniel P. Berrange return ret; 787a31bdae5SDaniel P. Berrange } 788a31bdae5SDaniel P. Berrange 789a31bdae5SDaniel P. Berrange 790a31bdae5SDaniel P. Berrange int object_set_propv(Object *obj, 791a31bdae5SDaniel P. Berrange Error **errp, 792a31bdae5SDaniel P. Berrange va_list vargs) 793a31bdae5SDaniel P. Berrange { 794a31bdae5SDaniel P. Berrange const char *propname; 795a31bdae5SDaniel P. Berrange Error *local_err = NULL; 796a31bdae5SDaniel P. Berrange 797a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *); 798a31bdae5SDaniel P. Berrange while (propname != NULL) { 799a31bdae5SDaniel P. Berrange const char *value = va_arg(vargs, char *); 800a31bdae5SDaniel P. Berrange 801a31bdae5SDaniel P. Berrange g_assert(value != NULL); 802a31bdae5SDaniel P. Berrange object_property_parse(obj, value, propname, &local_err); 803a31bdae5SDaniel P. Berrange if (local_err) { 804a31bdae5SDaniel P. Berrange error_propagate(errp, local_err); 805a31bdae5SDaniel P. Berrange return -1; 806a31bdae5SDaniel P. Berrange } 807a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *); 808a31bdae5SDaniel P. Berrange } 809a31bdae5SDaniel P. Berrange 810a31bdae5SDaniel P. Berrange return 0; 811a31bdae5SDaniel P. Berrange } 812a31bdae5SDaniel P. Berrange 813a31bdae5SDaniel P. Berrange 8142f28d2ffSAnthony Liguori Object *object_dynamic_cast(Object *obj, const char *typename) 8152f28d2ffSAnthony Liguori { 816b7f43fe4SPaolo Bonzini if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) { 817acc4af3fSPaolo Bonzini return obj; 818acc4af3fSPaolo Bonzini } 819acc4af3fSPaolo Bonzini 8202f28d2ffSAnthony Liguori return NULL; 8212f28d2ffSAnthony Liguori } 8222f28d2ffSAnthony Liguori 823be17f18bSPaolo Bonzini Object *object_dynamic_cast_assert(Object *obj, const char *typename, 824be17f18bSPaolo Bonzini const char *file, int line, const char *func) 8252f28d2ffSAnthony Liguori { 826fa131d94SPaolo Bonzini trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)", 827fa131d94SPaolo Bonzini typename, file, line, func); 828fa131d94SPaolo Bonzini 8293556c233SPaolo Bonzini #ifdef CONFIG_QOM_CAST_DEBUG 83003587328SAnthony Liguori int i; 83103587328SAnthony Liguori Object *inst; 83203587328SAnthony Liguori 83395916abcSPeter Crosthwaite for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { 834b6b3ccfdSAlex Bennée if (atomic_read(&obj->class->object_cast_cache[i]) == typename) { 83503587328SAnthony Liguori goto out; 83603587328SAnthony Liguori } 83703587328SAnthony Liguori } 83803587328SAnthony Liguori 83903587328SAnthony Liguori inst = object_dynamic_cast(obj, typename); 8402f28d2ffSAnthony Liguori 841b7f43fe4SPaolo Bonzini if (!inst && obj) { 842be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 843be17f18bSPaolo Bonzini file, line, func, obj, typename); 8442f28d2ffSAnthony Liguori abort(); 8452f28d2ffSAnthony Liguori } 8462f28d2ffSAnthony Liguori 8473556c233SPaolo Bonzini assert(obj == inst); 84803587328SAnthony Liguori 84995916abcSPeter Crosthwaite if (obj && obj == inst) { 85003587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 851b6b3ccfdSAlex Bennée atomic_set(&obj->class->object_cast_cache[i - 1], 852b6b3ccfdSAlex Bennée atomic_read(&obj->class->object_cast_cache[i])); 85303587328SAnthony Liguori } 854b6b3ccfdSAlex Bennée atomic_set(&obj->class->object_cast_cache[i - 1], typename); 85503587328SAnthony Liguori } 85603587328SAnthony Liguori 85703587328SAnthony Liguori out: 8583556c233SPaolo Bonzini #endif 8593556c233SPaolo Bonzini return obj; 8602f28d2ffSAnthony Liguori } 8612f28d2ffSAnthony Liguori 8622f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast(ObjectClass *class, 8632f28d2ffSAnthony Liguori const char *typename) 8642f28d2ffSAnthony Liguori { 86533e95c63SAnthony Liguori ObjectClass *ret = NULL; 866bf0fda34SPaolo Bonzini TypeImpl *target_type; 867bf0fda34SPaolo Bonzini TypeImpl *type; 8682f28d2ffSAnthony Liguori 869bf0fda34SPaolo Bonzini if (!class) { 870bf0fda34SPaolo Bonzini return NULL; 871bf0fda34SPaolo Bonzini } 872bf0fda34SPaolo Bonzini 873793c96b5SPaolo Bonzini /* A simple fast path that can trigger a lot for leaf classes. */ 874bf0fda34SPaolo Bonzini type = class->type; 875793c96b5SPaolo Bonzini if (type->name == typename) { 876793c96b5SPaolo Bonzini return class; 877793c96b5SPaolo Bonzini } 878793c96b5SPaolo Bonzini 879bf0fda34SPaolo Bonzini target_type = type_get_by_name(typename); 8809ab880b3SAlexander Graf if (!target_type) { 8819ab880b3SAlexander Graf /* target class type unknown, so fail the cast */ 8829ab880b3SAlexander Graf return NULL; 8839ab880b3SAlexander Graf } 8849ab880b3SAlexander Graf 88500e2ceaeSPeter Crosthwaite if (type->class->interfaces && 88600e2ceaeSPeter Crosthwaite type_is_ancestor(target_type, type_interface)) { 88733e95c63SAnthony Liguori int found = 0; 88833e95c63SAnthony Liguori GSList *i; 88933e95c63SAnthony Liguori 89033e95c63SAnthony Liguori for (i = class->interfaces; i; i = i->next) { 89133e95c63SAnthony Liguori ObjectClass *target_class = i->data; 89233e95c63SAnthony Liguori 89333e95c63SAnthony Liguori if (type_is_ancestor(target_class->type, target_type)) { 89433e95c63SAnthony Liguori ret = target_class; 89533e95c63SAnthony Liguori found++; 89633e95c63SAnthony Liguori } 8972f28d2ffSAnthony Liguori } 8982f28d2ffSAnthony Liguori 89933e95c63SAnthony Liguori /* The match was ambiguous, don't allow a cast */ 90033e95c63SAnthony Liguori if (found > 1) { 90133e95c63SAnthony Liguori ret = NULL; 90233e95c63SAnthony Liguori } 90333e95c63SAnthony Liguori } else if (type_is_ancestor(type, target_type)) { 90433e95c63SAnthony Liguori ret = class; 9052f28d2ffSAnthony Liguori } 9062f28d2ffSAnthony Liguori 90733e95c63SAnthony Liguori return ret; 9082f28d2ffSAnthony Liguori } 9092f28d2ffSAnthony Liguori 9102f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 911be17f18bSPaolo Bonzini const char *typename, 912be17f18bSPaolo Bonzini const char *file, int line, 913be17f18bSPaolo Bonzini const char *func) 9142f28d2ffSAnthony Liguori { 915fa131d94SPaolo Bonzini ObjectClass *ret; 9162f28d2ffSAnthony Liguori 917fa131d94SPaolo Bonzini trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)", 918fa131d94SPaolo Bonzini typename, file, line, func); 919fa131d94SPaolo Bonzini 92003587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG 92103587328SAnthony Liguori int i; 92203587328SAnthony Liguori 9239d6a3d58SPeter Crosthwaite for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { 924b6b3ccfdSAlex Bennée if (atomic_read(&class->class_cast_cache[i]) == typename) { 92503587328SAnthony Liguori ret = class; 92603587328SAnthony Liguori goto out; 92703587328SAnthony Liguori } 92803587328SAnthony Liguori } 92903587328SAnthony Liguori #else 9309d6a3d58SPeter Crosthwaite if (!class || !class->interfaces) { 9313556c233SPaolo Bonzini return class; 9323556c233SPaolo Bonzini } 9333556c233SPaolo Bonzini #endif 9343556c233SPaolo Bonzini 935fa131d94SPaolo Bonzini ret = object_class_dynamic_cast(class, typename); 936bf0fda34SPaolo Bonzini if (!ret && class) { 937be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 938be17f18bSPaolo Bonzini file, line, func, class, typename); 9392f28d2ffSAnthony Liguori abort(); 9402f28d2ffSAnthony Liguori } 9412f28d2ffSAnthony Liguori 94203587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG 9439d6a3d58SPeter Crosthwaite if (class && ret == class) { 94403587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 945b6b3ccfdSAlex Bennée atomic_set(&class->class_cast_cache[i - 1], 946b6b3ccfdSAlex Bennée atomic_read(&class->class_cast_cache[i])); 94703587328SAnthony Liguori } 948b6b3ccfdSAlex Bennée atomic_set(&class->class_cast_cache[i - 1], typename); 94903587328SAnthony Liguori } 95003587328SAnthony Liguori out: 95103587328SAnthony Liguori #endif 9522f28d2ffSAnthony Liguori return ret; 9532f28d2ffSAnthony Liguori } 9542f28d2ffSAnthony Liguori 9558f5d58efSIgor Mammedov const char *object_get_typename(const Object *obj) 9562f28d2ffSAnthony Liguori { 9572f28d2ffSAnthony Liguori return obj->class->type->name; 9582f28d2ffSAnthony Liguori } 9592f28d2ffSAnthony Liguori 9602f28d2ffSAnthony Liguori ObjectClass *object_get_class(Object *obj) 9612f28d2ffSAnthony Liguori { 9622f28d2ffSAnthony Liguori return obj->class; 9632f28d2ffSAnthony Liguori } 9642f28d2ffSAnthony Liguori 96517862378SAndreas Färber bool object_class_is_abstract(ObjectClass *klass) 96617862378SAndreas Färber { 96717862378SAndreas Färber return klass->type->abstract; 96817862378SAndreas Färber } 96917862378SAndreas Färber 9702f28d2ffSAnthony Liguori const char *object_class_get_name(ObjectClass *klass) 9712f28d2ffSAnthony Liguori { 9722f28d2ffSAnthony Liguori return klass->type->name; 9732f28d2ffSAnthony Liguori } 9742f28d2ffSAnthony Liguori 9752f28d2ffSAnthony Liguori ObjectClass *object_class_by_name(const char *typename) 9762f28d2ffSAnthony Liguori { 9772f28d2ffSAnthony Liguori TypeImpl *type = type_get_by_name(typename); 9782f28d2ffSAnthony Liguori 9792f28d2ffSAnthony Liguori if (!type) { 9802f28d2ffSAnthony Liguori return NULL; 9812f28d2ffSAnthony Liguori } 9822f28d2ffSAnthony Liguori 983ac451033SIgor Mitsyanko type_initialize(type); 9842f28d2ffSAnthony Liguori 9852f28d2ffSAnthony Liguori return type->class; 9862f28d2ffSAnthony Liguori } 9872f28d2ffSAnthony Liguori 9880f8198f1SGerd Hoffmann ObjectClass *module_object_class_by_name(const char *typename) 9890f8198f1SGerd Hoffmann { 9900f8198f1SGerd Hoffmann ObjectClass *oc; 9910f8198f1SGerd Hoffmann 9920f8198f1SGerd Hoffmann oc = object_class_by_name(typename); 9930f8198f1SGerd Hoffmann #ifdef CONFIG_MODULES 9940f8198f1SGerd Hoffmann if (!oc) { 9950f8198f1SGerd Hoffmann module_load_qom_one(typename); 9960f8198f1SGerd Hoffmann oc = object_class_by_name(typename); 9970f8198f1SGerd Hoffmann } 9980f8198f1SGerd Hoffmann #endif 9990f8198f1SGerd Hoffmann return oc; 10000f8198f1SGerd Hoffmann } 10010f8198f1SGerd Hoffmann 1002e7cce67fSPaolo Bonzini ObjectClass *object_class_get_parent(ObjectClass *class) 1003e7cce67fSPaolo Bonzini { 1004e7cce67fSPaolo Bonzini TypeImpl *type = type_get_parent(class->type); 1005e7cce67fSPaolo Bonzini 1006e7cce67fSPaolo Bonzini if (!type) { 1007e7cce67fSPaolo Bonzini return NULL; 1008e7cce67fSPaolo Bonzini } 1009e7cce67fSPaolo Bonzini 1010e7cce67fSPaolo Bonzini type_initialize(type); 1011e7cce67fSPaolo Bonzini 1012e7cce67fSPaolo Bonzini return type->class; 1013e7cce67fSPaolo Bonzini } 1014e7cce67fSPaolo Bonzini 10152f28d2ffSAnthony Liguori typedef struct OCFData 10162f28d2ffSAnthony Liguori { 10172f28d2ffSAnthony Liguori void (*fn)(ObjectClass *klass, void *opaque); 101893c511a1SAnthony Liguori const char *implements_type; 101993c511a1SAnthony Liguori bool include_abstract; 10202f28d2ffSAnthony Liguori void *opaque; 10212f28d2ffSAnthony Liguori } OCFData; 10222f28d2ffSAnthony Liguori 10232f28d2ffSAnthony Liguori static void object_class_foreach_tramp(gpointer key, gpointer value, 10242f28d2ffSAnthony Liguori gpointer opaque) 10252f28d2ffSAnthony Liguori { 10262f28d2ffSAnthony Liguori OCFData *data = opaque; 10272f28d2ffSAnthony Liguori TypeImpl *type = value; 102893c511a1SAnthony Liguori ObjectClass *k; 10292f28d2ffSAnthony Liguori 1030ac451033SIgor Mitsyanko type_initialize(type); 103193c511a1SAnthony Liguori k = type->class; 10322f28d2ffSAnthony Liguori 103393c511a1SAnthony Liguori if (!data->include_abstract && type->abstract) { 103493c511a1SAnthony Liguori return; 103593c511a1SAnthony Liguori } 103693c511a1SAnthony Liguori 103793c511a1SAnthony Liguori if (data->implements_type && 103893c511a1SAnthony Liguori !object_class_dynamic_cast(k, data->implements_type)) { 103993c511a1SAnthony Liguori return; 104093c511a1SAnthony Liguori } 104193c511a1SAnthony Liguori 104293c511a1SAnthony Liguori data->fn(k, data->opaque); 10432f28d2ffSAnthony Liguori } 10442f28d2ffSAnthony Liguori 10452f28d2ffSAnthony Liguori void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 104693c511a1SAnthony Liguori const char *implements_type, bool include_abstract, 10472f28d2ffSAnthony Liguori void *opaque) 10482f28d2ffSAnthony Liguori { 104993c511a1SAnthony Liguori OCFData data = { fn, implements_type, include_abstract, opaque }; 10502f28d2ffSAnthony Liguori 1051f54c19caSHervé Poussineau enumerating_types = true; 10522f28d2ffSAnthony Liguori g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 1053f54c19caSHervé Poussineau enumerating_types = false; 10542f28d2ffSAnthony Liguori } 105557c9fafeSAnthony Liguori 1056d714b8deSPeter Crosthwaite static int do_object_child_foreach(Object *obj, 1057d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque), 1058d714b8deSPeter Crosthwaite void *opaque, bool recurse) 105932efc535SPaolo Bonzini { 1060b604a854SPavel Fedin GHashTableIter iter; 1061b604a854SPavel Fedin ObjectProperty *prop; 106232efc535SPaolo Bonzini int ret = 0; 106332efc535SPaolo Bonzini 1064b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties); 1065b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 106632efc535SPaolo Bonzini if (object_property_is_child(prop)) { 1067d714b8deSPeter Crosthwaite Object *child = prop->opaque; 1068d714b8deSPeter Crosthwaite 1069d714b8deSPeter Crosthwaite ret = fn(child, opaque); 107032efc535SPaolo Bonzini if (ret != 0) { 107132efc535SPaolo Bonzini break; 107232efc535SPaolo Bonzini } 1073d714b8deSPeter Crosthwaite if (recurse) { 10744a39181dSCédric Le Goater ret = do_object_child_foreach(child, fn, opaque, true); 10754a39181dSCédric Le Goater if (ret != 0) { 10764a39181dSCédric Le Goater break; 10774a39181dSCédric Le Goater } 1078d714b8deSPeter Crosthwaite } 107932efc535SPaolo Bonzini } 108032efc535SPaolo Bonzini } 108132efc535SPaolo Bonzini return ret; 108232efc535SPaolo Bonzini } 108332efc535SPaolo Bonzini 1084d714b8deSPeter Crosthwaite int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), 1085d714b8deSPeter Crosthwaite void *opaque) 1086d714b8deSPeter Crosthwaite { 1087d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, false); 1088d714b8deSPeter Crosthwaite } 1089d714b8deSPeter Crosthwaite 1090d714b8deSPeter Crosthwaite int object_child_foreach_recursive(Object *obj, 1091d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque), 1092d714b8deSPeter Crosthwaite void *opaque) 1093d714b8deSPeter Crosthwaite { 1094d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, true); 1095d714b8deSPeter Crosthwaite } 1096d714b8deSPeter Crosthwaite 1097418ba9e5SAndreas Färber static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) 1098418ba9e5SAndreas Färber { 1099418ba9e5SAndreas Färber GSList **list = opaque; 1100418ba9e5SAndreas Färber 1101418ba9e5SAndreas Färber *list = g_slist_prepend(*list, klass); 1102418ba9e5SAndreas Färber } 1103418ba9e5SAndreas Färber 1104418ba9e5SAndreas Färber GSList *object_class_get_list(const char *implements_type, 1105418ba9e5SAndreas Färber bool include_abstract) 1106418ba9e5SAndreas Färber { 1107418ba9e5SAndreas Färber GSList *list = NULL; 1108418ba9e5SAndreas Färber 1109418ba9e5SAndreas Färber object_class_foreach(object_class_get_list_tramp, 1110418ba9e5SAndreas Färber implements_type, include_abstract, &list); 1111418ba9e5SAndreas Färber return list; 1112418ba9e5SAndreas Färber } 1113418ba9e5SAndreas Färber 111447c66009SPaolo Bonzini static gint object_class_cmp(gconstpointer a, gconstpointer b) 111547c66009SPaolo Bonzini { 111647c66009SPaolo Bonzini return strcasecmp(object_class_get_name((ObjectClass *)a), 111747c66009SPaolo Bonzini object_class_get_name((ObjectClass *)b)); 111847c66009SPaolo Bonzini } 111947c66009SPaolo Bonzini 112047c66009SPaolo Bonzini GSList *object_class_get_list_sorted(const char *implements_type, 112147c66009SPaolo Bonzini bool include_abstract) 112247c66009SPaolo Bonzini { 112347c66009SPaolo Bonzini return g_slist_sort(object_class_get_list(implements_type, include_abstract), 112447c66009SPaolo Bonzini object_class_cmp); 112547c66009SPaolo Bonzini } 112647c66009SPaolo Bonzini 1127b77ade9bSMarc-André Lureau Object *object_ref(Object *obj) 112857c9fafeSAnthony Liguori { 11298ffad850SPeter Crosthwaite if (!obj) { 1130b77ade9bSMarc-André Lureau return NULL; 11318ffad850SPeter Crosthwaite } 1132f08c03f3SJan Kiszka atomic_inc(&obj->ref); 1133b77ade9bSMarc-André Lureau return obj; 113457c9fafeSAnthony Liguori } 113557c9fafeSAnthony Liguori 113657c9fafeSAnthony Liguori void object_unref(Object *obj) 113757c9fafeSAnthony Liguori { 11388ffad850SPeter Crosthwaite if (!obj) { 11398ffad850SPeter Crosthwaite return; 11408ffad850SPeter Crosthwaite } 1141719a3077SMarkus Armbruster g_assert(obj->ref > 0); 114257c9fafeSAnthony Liguori 114357c9fafeSAnthony Liguori /* parent always holds a reference to its children */ 1144f08c03f3SJan Kiszka if (atomic_fetch_dec(&obj->ref) == 1) { 114557c9fafeSAnthony Liguori object_finalize(obj); 114657c9fafeSAnthony Liguori } 114757c9fafeSAnthony Liguori } 114857c9fafeSAnthony Liguori 1149d2623129SMarkus Armbruster static ObjectProperty * 1150d2623129SMarkus Armbruster object_property_try_add(Object *obj, const char *name, const char *type, 115157c9fafeSAnthony Liguori ObjectPropertyAccessor *get, 115257c9fafeSAnthony Liguori ObjectPropertyAccessor *set, 115357c9fafeSAnthony Liguori ObjectPropertyRelease *release, 115457c9fafeSAnthony Liguori void *opaque, Error **errp) 115557c9fafeSAnthony Liguori { 115654852b03SPeter Maydell ObjectProperty *prop; 115733965904SPeter Crosthwaite size_t name_len = strlen(name); 115833965904SPeter Crosthwaite 115933965904SPeter Crosthwaite if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { 116033965904SPeter Crosthwaite int i; 116133965904SPeter Crosthwaite ObjectProperty *ret; 116233965904SPeter Crosthwaite char *name_no_array = g_strdup(name); 116333965904SPeter Crosthwaite 116433965904SPeter Crosthwaite name_no_array[name_len - 3] = '\0'; 116533965904SPeter Crosthwaite for (i = 0; ; ++i) { 116633965904SPeter Crosthwaite char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); 116733965904SPeter Crosthwaite 1168d2623129SMarkus Armbruster ret = object_property_try_add(obj, full_name, type, get, set, 116933965904SPeter Crosthwaite release, opaque, NULL); 117033965904SPeter Crosthwaite g_free(full_name); 117133965904SPeter Crosthwaite if (ret) { 117233965904SPeter Crosthwaite break; 117333965904SPeter Crosthwaite } 117433965904SPeter Crosthwaite } 117533965904SPeter Crosthwaite g_free(name_no_array); 117633965904SPeter Crosthwaite return ret; 117733965904SPeter Crosthwaite } 117854852b03SPeter Maydell 117916bf7f52SDaniel P. Berrange if (object_property_find(obj, name, NULL) != NULL) { 1180d55e937dSGreg Kurz error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')", 1181d55e937dSGreg Kurz name, object_get_typename(obj)); 118264607d08SPaolo Bonzini return NULL; 118354852b03SPeter Maydell } 118454852b03SPeter Maydell 118554852b03SPeter Maydell prop = g_malloc0(sizeof(*prop)); 118657c9fafeSAnthony Liguori 118757c9fafeSAnthony Liguori prop->name = g_strdup(name); 118857c9fafeSAnthony Liguori prop->type = g_strdup(type); 118957c9fafeSAnthony Liguori 119057c9fafeSAnthony Liguori prop->get = get; 119157c9fafeSAnthony Liguori prop->set = set; 119257c9fafeSAnthony Liguori prop->release = release; 119357c9fafeSAnthony Liguori prop->opaque = opaque; 119457c9fafeSAnthony Liguori 1195b604a854SPavel Fedin g_hash_table_insert(obj->properties, prop->name, prop); 119664607d08SPaolo Bonzini return prop; 119757c9fafeSAnthony Liguori } 119857c9fafeSAnthony Liguori 119916bf7f52SDaniel P. Berrange ObjectProperty * 1200d2623129SMarkus Armbruster object_property_add(Object *obj, const char *name, const char *type, 1201d2623129SMarkus Armbruster ObjectPropertyAccessor *get, 1202d2623129SMarkus Armbruster ObjectPropertyAccessor *set, 1203d2623129SMarkus Armbruster ObjectPropertyRelease *release, 1204d2623129SMarkus Armbruster void *opaque) 1205d2623129SMarkus Armbruster { 1206d2623129SMarkus Armbruster return object_property_try_add(obj, name, type, get, set, release, 1207d2623129SMarkus Armbruster opaque, &error_abort); 1208d2623129SMarkus Armbruster } 1209d2623129SMarkus Armbruster 1210d2623129SMarkus Armbruster ObjectProperty * 121116bf7f52SDaniel P. Berrange object_class_property_add(ObjectClass *klass, 121216bf7f52SDaniel P. Berrange const char *name, 121316bf7f52SDaniel P. Berrange const char *type, 121416bf7f52SDaniel P. Berrange ObjectPropertyAccessor *get, 121516bf7f52SDaniel P. Berrange ObjectPropertyAccessor *set, 121616bf7f52SDaniel P. Berrange ObjectPropertyRelease *release, 1217d2623129SMarkus Armbruster void *opaque) 121816bf7f52SDaniel P. Berrange { 121916bf7f52SDaniel P. Berrange ObjectProperty *prop; 122016bf7f52SDaniel P. Berrange 1221d2623129SMarkus Armbruster assert(!object_class_property_find(klass, name, NULL)); 122216bf7f52SDaniel P. Berrange 122316bf7f52SDaniel P. Berrange prop = g_malloc0(sizeof(*prop)); 122416bf7f52SDaniel P. Berrange 122516bf7f52SDaniel P. Berrange prop->name = g_strdup(name); 122616bf7f52SDaniel P. Berrange prop->type = g_strdup(type); 122716bf7f52SDaniel P. Berrange 122816bf7f52SDaniel P. Berrange prop->get = get; 122916bf7f52SDaniel P. Berrange prop->set = set; 123016bf7f52SDaniel P. Berrange prop->release = release; 123116bf7f52SDaniel P. Berrange prop->opaque = opaque; 123216bf7f52SDaniel P. Berrange 1233ba806ffbSMarc-André Lureau g_hash_table_insert(klass->properties, prop->name, prop); 123416bf7f52SDaniel P. Berrange 123516bf7f52SDaniel P. Berrange return prop; 123616bf7f52SDaniel P. Berrange } 123716bf7f52SDaniel P. Berrange 123889bfe000SPaolo Bonzini ObjectProperty *object_property_find(Object *obj, const char *name, 123989bfe000SPaolo Bonzini Error **errp) 124057c9fafeSAnthony Liguori { 124157c9fafeSAnthony Liguori ObjectProperty *prop; 124216bf7f52SDaniel P. Berrange ObjectClass *klass = object_get_class(obj); 124316bf7f52SDaniel P. Berrange 124416bf7f52SDaniel P. Berrange prop = object_class_property_find(klass, name, NULL); 124516bf7f52SDaniel P. Berrange if (prop) { 124616bf7f52SDaniel P. Berrange return prop; 124716bf7f52SDaniel P. Berrange } 124857c9fafeSAnthony Liguori 1249b604a854SPavel Fedin prop = g_hash_table_lookup(obj->properties, name); 1250b604a854SPavel Fedin if (prop) { 125157c9fafeSAnthony Liguori return prop; 125257c9fafeSAnthony Liguori } 125357c9fafeSAnthony Liguori 1254f231b88dSCole Robinson error_setg(errp, "Property '.%s' not found", name); 125557c9fafeSAnthony Liguori return NULL; 125657c9fafeSAnthony Liguori } 125757c9fafeSAnthony Liguori 12587746abd8SDaniel P. Berrange void object_property_iter_init(ObjectPropertyIterator *iter, 12597746abd8SDaniel P. Berrange Object *obj) 1260a00c9482SDaniel P. Berrange { 12617746abd8SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, obj->properties); 12627746abd8SDaniel P. Berrange iter->nextclass = object_get_class(obj); 1263a00c9482SDaniel P. Berrange } 1264a00c9482SDaniel P. Berrange 1265a00c9482SDaniel P. Berrange ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) 1266a00c9482SDaniel P. Berrange { 1267b604a854SPavel Fedin gpointer key, val; 126816bf7f52SDaniel P. Berrange while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { 126916bf7f52SDaniel P. Berrange if (!iter->nextclass) { 1270b604a854SPavel Fedin return NULL; 1271a00c9482SDaniel P. Berrange } 127216bf7f52SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, iter->nextclass->properties); 127316bf7f52SDaniel P. Berrange iter->nextclass = object_class_get_parent(iter->nextclass); 127416bf7f52SDaniel P. Berrange } 1275b604a854SPavel Fedin return val; 1276a00c9482SDaniel P. Berrange } 1277a00c9482SDaniel P. Berrange 1278961c47bbSAlexey Kardashevskiy void object_class_property_iter_init(ObjectPropertyIterator *iter, 1279961c47bbSAlexey Kardashevskiy ObjectClass *klass) 1280961c47bbSAlexey Kardashevskiy { 1281961c47bbSAlexey Kardashevskiy g_hash_table_iter_init(&iter->iter, klass->properties); 1282684546d8SMarc-André Lureau iter->nextclass = object_class_get_parent(klass); 1283961c47bbSAlexey Kardashevskiy } 1284961c47bbSAlexey Kardashevskiy 128516bf7f52SDaniel P. Berrange ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, 128616bf7f52SDaniel P. Berrange Error **errp) 128716bf7f52SDaniel P. Berrange { 128816bf7f52SDaniel P. Berrange ObjectProperty *prop; 128916bf7f52SDaniel P. Berrange ObjectClass *parent_klass; 129016bf7f52SDaniel P. Berrange 129116bf7f52SDaniel P. Berrange parent_klass = object_class_get_parent(klass); 129216bf7f52SDaniel P. Berrange if (parent_klass) { 129316bf7f52SDaniel P. Berrange prop = object_class_property_find(parent_klass, name, NULL); 129416bf7f52SDaniel P. Berrange if (prop) { 129516bf7f52SDaniel P. Berrange return prop; 129616bf7f52SDaniel P. Berrange } 129716bf7f52SDaniel P. Berrange } 129816bf7f52SDaniel P. Berrange 129916bf7f52SDaniel P. Berrange prop = g_hash_table_lookup(klass->properties, name); 130016bf7f52SDaniel P. Berrange if (!prop) { 130116bf7f52SDaniel P. Berrange error_setg(errp, "Property '.%s' not found", name); 130216bf7f52SDaniel P. Berrange } 130316bf7f52SDaniel P. Berrange return prop; 130416bf7f52SDaniel P. Berrange } 130516bf7f52SDaniel P. Berrange 1306df4fe0b2SMarkus Armbruster void object_property_del(Object *obj, const char *name) 130757c9fafeSAnthony Liguori { 1308b604a854SPavel Fedin ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); 1309b604a854SPavel Fedin 13100866aca1SAnthony Liguori if (prop->release) { 13110866aca1SAnthony Liguori prop->release(obj, name, prop->opaque); 13120866aca1SAnthony Liguori } 1313b604a854SPavel Fedin g_hash_table_remove(obj->properties, name); 131457c9fafeSAnthony Liguori } 131557c9fafeSAnthony Liguori 131657c9fafeSAnthony Liguori void object_property_get(Object *obj, Visitor *v, const char *name, 131757c9fafeSAnthony Liguori Error **errp) 131857c9fafeSAnthony Liguori { 131989bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 132057c9fafeSAnthony Liguori if (prop == NULL) { 132157c9fafeSAnthony Liguori return; 132257c9fafeSAnthony Liguori } 132357c9fafeSAnthony Liguori 132457c9fafeSAnthony Liguori if (!prop->get) { 1325c6bd8c70SMarkus Armbruster error_setg(errp, QERR_PERMISSION_DENIED); 132657c9fafeSAnthony Liguori } else { 1327d7bce999SEric Blake prop->get(obj, v, name, prop->opaque, errp); 132857c9fafeSAnthony Liguori } 132957c9fafeSAnthony Liguori } 133057c9fafeSAnthony Liguori 133157c9fafeSAnthony Liguori void object_property_set(Object *obj, Visitor *v, const char *name, 133257c9fafeSAnthony Liguori Error **errp) 133357c9fafeSAnthony Liguori { 133489bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 133557c9fafeSAnthony Liguori if (prop == NULL) { 133657c9fafeSAnthony Liguori return; 133757c9fafeSAnthony Liguori } 133857c9fafeSAnthony Liguori 133957c9fafeSAnthony Liguori if (!prop->set) { 1340c6bd8c70SMarkus Armbruster error_setg(errp, QERR_PERMISSION_DENIED); 134157c9fafeSAnthony Liguori } else { 1342d7bce999SEric Blake prop->set(obj, v, name, prop->opaque, errp); 134357c9fafeSAnthony Liguori } 134457c9fafeSAnthony Liguori } 134557c9fafeSAnthony Liguori 13467b7b7d18SPaolo Bonzini void object_property_set_str(Object *obj, const char *value, 13477b7b7d18SPaolo Bonzini const char *name, Error **errp) 13487b7b7d18SPaolo Bonzini { 13497b7b7d18SPaolo Bonzini QString *qstr = qstring_from_str(value); 13507b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qstr), name, errp); 13517b7b7d18SPaolo Bonzini 1352cb3e7f08SMarc-André Lureau qobject_unref(qstr); 13537b7b7d18SPaolo Bonzini } 13547b7b7d18SPaolo Bonzini 13557b7b7d18SPaolo Bonzini char *object_property_get_str(Object *obj, const char *name, 13567b7b7d18SPaolo Bonzini Error **errp) 13577b7b7d18SPaolo Bonzini { 13587b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 13597b7b7d18SPaolo Bonzini char *retval; 13607b7b7d18SPaolo Bonzini 13617b7b7d18SPaolo Bonzini if (!ret) { 13627b7b7d18SPaolo Bonzini return NULL; 13637b7b7d18SPaolo Bonzini } 1364aafb21a0SPeter Xu 1365aafb21a0SPeter Xu retval = g_strdup(qobject_get_try_str(ret)); 1366aafb21a0SPeter Xu if (!retval) { 1367c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); 13687b7b7d18SPaolo Bonzini } 13697b7b7d18SPaolo Bonzini 1370cb3e7f08SMarc-André Lureau qobject_unref(ret); 13717b7b7d18SPaolo Bonzini return retval; 13727b7b7d18SPaolo Bonzini } 13737b7b7d18SPaolo Bonzini 13741d9c5a12SPaolo Bonzini void object_property_set_link(Object *obj, Object *value, 13751d9c5a12SPaolo Bonzini const char *name, Error **errp) 13761d9c5a12SPaolo Bonzini { 1377d3c49316SPeter Crosthwaite if (value) { 1378ddfb0baaSMarkus Armbruster char *path = object_get_canonical_path(value); 13792d3aa28cSVlad Yasevich object_property_set_str(obj, path, name, errp); 13802d3aa28cSVlad Yasevich g_free(path); 1381d3c49316SPeter Crosthwaite } else { 1382d3c49316SPeter Crosthwaite object_property_set_str(obj, "", name, errp); 1383d3c49316SPeter Crosthwaite } 13841d9c5a12SPaolo Bonzini } 13851d9c5a12SPaolo Bonzini 13861d9c5a12SPaolo Bonzini Object *object_property_get_link(Object *obj, const char *name, 13871d9c5a12SPaolo Bonzini Error **errp) 13881d9c5a12SPaolo Bonzini { 13891d9c5a12SPaolo Bonzini char *str = object_property_get_str(obj, name, errp); 13901d9c5a12SPaolo Bonzini Object *target = NULL; 13911d9c5a12SPaolo Bonzini 13921d9c5a12SPaolo Bonzini if (str && *str) { 13931d9c5a12SPaolo Bonzini target = object_resolve_path(str, NULL); 13941d9c5a12SPaolo Bonzini if (!target) { 139575158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 139675158ebbSMarkus Armbruster "Device '%s' not found", str); 13971d9c5a12SPaolo Bonzini } 13981d9c5a12SPaolo Bonzini } 13991d9c5a12SPaolo Bonzini 14001d9c5a12SPaolo Bonzini g_free(str); 14011d9c5a12SPaolo Bonzini return target; 14021d9c5a12SPaolo Bonzini } 14031d9c5a12SPaolo Bonzini 14047b7b7d18SPaolo Bonzini void object_property_set_bool(Object *obj, bool value, 14057b7b7d18SPaolo Bonzini const char *name, Error **errp) 14067b7b7d18SPaolo Bonzini { 1407fc48ffc3SEric Blake QBool *qbool = qbool_from_bool(value); 14087b7b7d18SPaolo Bonzini object_property_set_qobject(obj, QOBJECT(qbool), name, errp); 14097b7b7d18SPaolo Bonzini 1410cb3e7f08SMarc-André Lureau qobject_unref(qbool); 14117b7b7d18SPaolo Bonzini } 14127b7b7d18SPaolo Bonzini 14137b7b7d18SPaolo Bonzini bool object_property_get_bool(Object *obj, const char *name, 14147b7b7d18SPaolo Bonzini Error **errp) 14157b7b7d18SPaolo Bonzini { 14167b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 14177b7b7d18SPaolo Bonzini QBool *qbool; 14187b7b7d18SPaolo Bonzini bool retval; 14197b7b7d18SPaolo Bonzini 14207b7b7d18SPaolo Bonzini if (!ret) { 14217b7b7d18SPaolo Bonzini return false; 14227b7b7d18SPaolo Bonzini } 14237dc847ebSMax Reitz qbool = qobject_to(QBool, ret); 14247b7b7d18SPaolo Bonzini if (!qbool) { 1425c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); 14267b7b7d18SPaolo Bonzini retval = false; 14277b7b7d18SPaolo Bonzini } else { 1428fc48ffc3SEric Blake retval = qbool_get_bool(qbool); 14297b7b7d18SPaolo Bonzini } 14307b7b7d18SPaolo Bonzini 1431cb3e7f08SMarc-André Lureau qobject_unref(ret); 14327b7b7d18SPaolo Bonzini return retval; 14337b7b7d18SPaolo Bonzini } 14347b7b7d18SPaolo Bonzini 14357b7b7d18SPaolo Bonzini void object_property_set_int(Object *obj, int64_t value, 14367b7b7d18SPaolo Bonzini const char *name, Error **errp) 14377b7b7d18SPaolo Bonzini { 143801b2ffceSMarc-André Lureau QNum *qnum = qnum_from_int(value); 143901b2ffceSMarc-André Lureau object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 14407b7b7d18SPaolo Bonzini 1441cb3e7f08SMarc-André Lureau qobject_unref(qnum); 14427b7b7d18SPaolo Bonzini } 14437b7b7d18SPaolo Bonzini 14447b7b7d18SPaolo Bonzini int64_t object_property_get_int(Object *obj, const char *name, 14457b7b7d18SPaolo Bonzini Error **errp) 14467b7b7d18SPaolo Bonzini { 14477b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp); 144801b2ffceSMarc-André Lureau QNum *qnum; 14497b7b7d18SPaolo Bonzini int64_t retval; 14507b7b7d18SPaolo Bonzini 14517b7b7d18SPaolo Bonzini if (!ret) { 14527b7b7d18SPaolo Bonzini return -1; 14537b7b7d18SPaolo Bonzini } 145401b2ffceSMarc-André Lureau 14557dc847ebSMax Reitz qnum = qobject_to(QNum, ret); 145601b2ffceSMarc-André Lureau if (!qnum || !qnum_get_try_int(qnum, &retval)) { 1457c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); 14587b7b7d18SPaolo Bonzini retval = -1; 14597b7b7d18SPaolo Bonzini } 14607b7b7d18SPaolo Bonzini 1461cb3e7f08SMarc-André Lureau qobject_unref(ret); 14627b7b7d18SPaolo Bonzini return retval; 14637b7b7d18SPaolo Bonzini } 14647b7b7d18SPaolo Bonzini 14650e76ed0aSMarc-André Lureau static void object_property_init_defval(Object *obj, ObjectProperty *prop) 14660e76ed0aSMarc-André Lureau { 14670e76ed0aSMarc-André Lureau Visitor *v = qobject_input_visitor_new(prop->defval); 14680e76ed0aSMarc-André Lureau 14690e76ed0aSMarc-André Lureau assert(prop->set != NULL); 14700e76ed0aSMarc-André Lureau prop->set(obj, v, prop->name, prop->opaque, &error_abort); 14710e76ed0aSMarc-André Lureau 14720e76ed0aSMarc-André Lureau visit_free(v); 14730e76ed0aSMarc-André Lureau } 14740e76ed0aSMarc-André Lureau 14750e76ed0aSMarc-André Lureau static void object_property_set_default(ObjectProperty *prop, QObject *defval) 14760e76ed0aSMarc-André Lureau { 14770e76ed0aSMarc-André Lureau assert(!prop->defval); 14780e76ed0aSMarc-André Lureau assert(!prop->init); 14790e76ed0aSMarc-André Lureau 14800e76ed0aSMarc-André Lureau prop->defval = defval; 14810e76ed0aSMarc-André Lureau prop->init = object_property_init_defval; 14820e76ed0aSMarc-André Lureau } 14830e76ed0aSMarc-André Lureau 14840e76ed0aSMarc-André Lureau void object_property_set_default_bool(ObjectProperty *prop, bool value) 14850e76ed0aSMarc-André Lureau { 14860e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qbool_from_bool(value))); 14870e76ed0aSMarc-André Lureau } 14880e76ed0aSMarc-André Lureau 14890e76ed0aSMarc-André Lureau void object_property_set_default_str(ObjectProperty *prop, const char *value) 14900e76ed0aSMarc-André Lureau { 14910e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qstring_from_str(value))); 14920e76ed0aSMarc-André Lureau } 14930e76ed0aSMarc-André Lureau 14940e76ed0aSMarc-André Lureau void object_property_set_default_int(ObjectProperty *prop, int64_t value) 14950e76ed0aSMarc-André Lureau { 14960e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qnum_from_int(value))); 14970e76ed0aSMarc-André Lureau } 14980e76ed0aSMarc-André Lureau 14990e76ed0aSMarc-André Lureau void object_property_set_default_uint(ObjectProperty *prop, uint64_t value) 15000e76ed0aSMarc-André Lureau { 15010e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qnum_from_uint(value))); 15020e76ed0aSMarc-André Lureau } 15030e76ed0aSMarc-André Lureau 15043152779cSMarc-André Lureau void object_property_set_uint(Object *obj, uint64_t value, 15053152779cSMarc-André Lureau const char *name, Error **errp) 15063152779cSMarc-André Lureau { 15073152779cSMarc-André Lureau QNum *qnum = qnum_from_uint(value); 15083152779cSMarc-André Lureau 15093152779cSMarc-André Lureau object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 1510cb3e7f08SMarc-André Lureau qobject_unref(qnum); 15113152779cSMarc-André Lureau } 15123152779cSMarc-André Lureau 15133152779cSMarc-André Lureau uint64_t object_property_get_uint(Object *obj, const char *name, 15143152779cSMarc-André Lureau Error **errp) 15153152779cSMarc-André Lureau { 15163152779cSMarc-André Lureau QObject *ret = object_property_get_qobject(obj, name, errp); 15173152779cSMarc-André Lureau QNum *qnum; 15183152779cSMarc-André Lureau uint64_t retval; 15193152779cSMarc-André Lureau 15203152779cSMarc-André Lureau if (!ret) { 15213152779cSMarc-André Lureau return 0; 15223152779cSMarc-André Lureau } 15237dc847ebSMax Reitz qnum = qobject_to(QNum, ret); 15243152779cSMarc-André Lureau if (!qnum || !qnum_get_try_uint(qnum, &retval)) { 15253152779cSMarc-André Lureau error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint"); 15263152779cSMarc-André Lureau retval = 0; 15273152779cSMarc-André Lureau } 15283152779cSMarc-André Lureau 1529cb3e7f08SMarc-André Lureau qobject_unref(ret); 15303152779cSMarc-André Lureau return retval; 15313152779cSMarc-André Lureau } 15323152779cSMarc-André Lureau 1533a8e3fbedSDaniel P. Berrange typedef struct EnumProperty { 1534f7abe0ecSMarc-André Lureau const QEnumLookup *lookup; 1535a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **); 1536a8e3fbedSDaniel P. Berrange void (*set)(Object *, int, Error **); 1537a8e3fbedSDaniel P. Berrange } EnumProperty; 1538a8e3fbedSDaniel P. Berrange 15391f21772dSHu Tao int object_property_get_enum(Object *obj, const char *name, 1540a3590dacSDaniel P. Berrange const char *typename, Error **errp) 15411f21772dSHu Tao { 1542976620acSChen Fan char *str; 15431f21772dSHu Tao int ret; 1544a3590dacSDaniel P. Berrange ObjectProperty *prop = object_property_find(obj, name, errp); 1545a3590dacSDaniel P. Berrange EnumProperty *enumprop; 1546a3590dacSDaniel P. Berrange 1547a3590dacSDaniel P. Berrange if (prop == NULL) { 1548a3590dacSDaniel P. Berrange return 0; 1549a3590dacSDaniel P. Berrange } 1550a3590dacSDaniel P. Berrange 1551a3590dacSDaniel P. Berrange if (!g_str_equal(prop->type, typename)) { 1552a3590dacSDaniel P. Berrange error_setg(errp, "Property %s on %s is not '%s' enum type", 1553a3590dacSDaniel P. Berrange name, object_class_get_name( 1554a3590dacSDaniel P. Berrange object_get_class(obj)), typename); 1555a3590dacSDaniel P. Berrange return 0; 1556a3590dacSDaniel P. Berrange } 1557a3590dacSDaniel P. Berrange 1558a3590dacSDaniel P. Berrange enumprop = prop->opaque; 15591f21772dSHu Tao 1560b555f89fSMarkus Armbruster str = object_property_get_str(obj, name, errp); 1561b555f89fSMarkus Armbruster if (!str) { 15624715d42eSMarkus Armbruster return 0; 15634715d42eSMarkus Armbruster } 1564976620acSChen Fan 1565ea097dffSMarkus Armbruster ret = qapi_enum_parse(enumprop->lookup, str, -1, errp); 1566976620acSChen Fan g_free(str); 15671f21772dSHu Tao 15681f21772dSHu Tao return ret; 15691f21772dSHu Tao } 15701f21772dSHu Tao 1571b2cd7deeSPaolo Bonzini void object_property_parse(Object *obj, const char *string, 1572b2cd7deeSPaolo Bonzini const char *name, Error **errp) 1573b2cd7deeSPaolo Bonzini { 15747a0525c7SEric Blake Visitor *v = string_input_visitor_new(string); 15757a0525c7SEric Blake object_property_set(obj, v, name, errp); 15767a0525c7SEric Blake visit_free(v); 1577b2cd7deeSPaolo Bonzini } 1578b2cd7deeSPaolo Bonzini 15790b7593e0SPaolo Bonzini char *object_property_print(Object *obj, const char *name, bool human, 1580b2cd7deeSPaolo Bonzini Error **errp) 1581b2cd7deeSPaolo Bonzini { 15823b098d56SEric Blake Visitor *v; 15833a53009fSGonglei char *string = NULL; 15843a53009fSGonglei Error *local_err = NULL; 1585b2cd7deeSPaolo Bonzini 15863b098d56SEric Blake v = string_output_visitor_new(human, &string); 15873b098d56SEric Blake object_property_get(obj, v, name, &local_err); 15883a53009fSGonglei if (local_err) { 15893a53009fSGonglei error_propagate(errp, local_err); 15903a53009fSGonglei goto out; 15913a53009fSGonglei } 15923a53009fSGonglei 15933b098d56SEric Blake visit_complete(v, &string); 15943a53009fSGonglei 15953a53009fSGonglei out: 15963b098d56SEric Blake visit_free(v); 1597b2cd7deeSPaolo Bonzini return string; 1598b2cd7deeSPaolo Bonzini } 1599b2cd7deeSPaolo Bonzini 160057c9fafeSAnthony Liguori const char *object_property_get_type(Object *obj, const char *name, Error **errp) 160157c9fafeSAnthony Liguori { 160289bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(obj, name, errp); 160357c9fafeSAnthony Liguori if (prop == NULL) { 160457c9fafeSAnthony Liguori return NULL; 160557c9fafeSAnthony Liguori } 160657c9fafeSAnthony Liguori 160757c9fafeSAnthony Liguori return prop->type; 160857c9fafeSAnthony Liguori } 160957c9fafeSAnthony Liguori 161057c9fafeSAnthony Liguori Object *object_get_root(void) 161157c9fafeSAnthony Liguori { 16128b45d447SAnthony Liguori static Object *root; 161357c9fafeSAnthony Liguori 16148b45d447SAnthony Liguori if (!root) { 16158b45d447SAnthony Liguori root = object_new("container"); 161657c9fafeSAnthony Liguori } 161757c9fafeSAnthony Liguori 16188b45d447SAnthony Liguori return root; 161957c9fafeSAnthony Liguori } 162057c9fafeSAnthony Liguori 1621bc2256c4SDaniel P. Berrange Object *object_get_objects_root(void) 1622bc2256c4SDaniel P. Berrange { 1623bc2256c4SDaniel P. Berrange return container_get(object_get_root(), "/objects"); 1624bc2256c4SDaniel P. Berrange } 1625bc2256c4SDaniel P. Berrange 16267c47c4eaSPeter Xu Object *object_get_internal_root(void) 16277c47c4eaSPeter Xu { 16287c47c4eaSPeter Xu static Object *internal_root; 16297c47c4eaSPeter Xu 16307c47c4eaSPeter Xu if (!internal_root) { 16317c47c4eaSPeter Xu internal_root = object_new("container"); 16327c47c4eaSPeter Xu } 16337c47c4eaSPeter Xu 16347c47c4eaSPeter Xu return internal_root; 16357c47c4eaSPeter Xu } 16367c47c4eaSPeter Xu 1637d7bce999SEric Blake static void object_get_child_property(Object *obj, Visitor *v, 1638d7bce999SEric Blake const char *name, void *opaque, 1639d7bce999SEric Blake Error **errp) 164057c9fafeSAnthony Liguori { 164157c9fafeSAnthony Liguori Object *child = opaque; 1642ddfb0baaSMarkus Armbruster char *path; 164357c9fafeSAnthony Liguori 164457c9fafeSAnthony Liguori path = object_get_canonical_path(child); 164551e72bc1SEric Blake visit_type_str(v, name, &path, errp); 164657c9fafeSAnthony Liguori g_free(path); 164757c9fafeSAnthony Liguori } 164857c9fafeSAnthony Liguori 1649ddfb0baaSMarkus Armbruster static Object *object_resolve_child_property(Object *parent, void *opaque, 1650ddfb0baaSMarkus Armbruster const char *part) 165164607d08SPaolo Bonzini { 165264607d08SPaolo Bonzini return opaque; 165364607d08SPaolo Bonzini } 165464607d08SPaolo Bonzini 1655db85b575SAnthony Liguori static void object_finalize_child_property(Object *obj, const char *name, 1656db85b575SAnthony Liguori void *opaque) 1657db85b575SAnthony Liguori { 1658db85b575SAnthony Liguori Object *child = opaque; 1659db85b575SAnthony Liguori 1660bffc687dSPaolo Bonzini if (child->class->unparent) { 1661bffc687dSPaolo Bonzini (child->class->unparent)(child); 1662bffc687dSPaolo Bonzini } 1663bffc687dSPaolo Bonzini child->parent = NULL; 1664db85b575SAnthony Liguori object_unref(child); 1665db85b575SAnthony Liguori } 1666db85b575SAnthony Liguori 166770251887SMarkus Armbruster ObjectProperty * 166870251887SMarkus Armbruster object_property_add_child(Object *obj, const char *name, 1669d2623129SMarkus Armbruster Object *child) 167057c9fafeSAnthony Liguori { 167170251887SMarkus Armbruster g_autofree char *type = NULL; 167264607d08SPaolo Bonzini ObjectProperty *op; 167357c9fafeSAnthony Liguori 1674d2623129SMarkus Armbruster assert(!child->parent); 16758faa2f85SPeter Crosthwaite 1676688ffbb4SPhilippe Mathieu-Daudé type = g_strdup_printf("child<%s>", object_get_typename(child)); 167757c9fafeSAnthony Liguori 167864607d08SPaolo Bonzini op = object_property_add(obj, name, type, object_get_child_property, NULL, 1679d2623129SMarkus Armbruster object_finalize_child_property, child); 168064607d08SPaolo Bonzini op->resolve = object_resolve_child_property; 168157c9fafeSAnthony Liguori object_ref(child); 168257c9fafeSAnthony Liguori child->parent = obj; 168370251887SMarkus Armbruster return op; 168457c9fafeSAnthony Liguori } 168557c9fafeSAnthony Liguori 16868f5d58efSIgor Mammedov void object_property_allow_set_link(const Object *obj, const char *name, 168739f72ef9SStefan Hajnoczi Object *val, Error **errp) 168839f72ef9SStefan Hajnoczi { 168939f72ef9SStefan Hajnoczi /* Allow the link to be set, always */ 169039f72ef9SStefan Hajnoczi } 169139f72ef9SStefan Hajnoczi 16929561fda8SStefan Hajnoczi typedef struct { 16939941d37bSMarc-André Lureau union { 169436854207SMarc-André Lureau Object **targetp; 16959941d37bSMarc-André Lureau Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer */ 1696840ecdfbSMarc-André Lureau ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */ 16979941d37bSMarc-André Lureau }; 16988f5d58efSIgor Mammedov void (*check)(const Object *, const char *, Object *, Error **); 16999561fda8SStefan Hajnoczi ObjectPropertyLinkFlags flags; 17009561fda8SStefan Hajnoczi } LinkProperty; 17019561fda8SStefan Hajnoczi 17029941d37bSMarc-André Lureau static Object ** 17039941d37bSMarc-André Lureau object_link_get_targetp(Object *obj, LinkProperty *lprop) 17049941d37bSMarc-André Lureau { 17059941d37bSMarc-André Lureau if (lprop->flags & OBJ_PROP_LINK_DIRECT) { 17069941d37bSMarc-André Lureau return &lprop->target; 1707840ecdfbSMarc-André Lureau } else if (lprop->flags & OBJ_PROP_LINK_CLASS) { 1708840ecdfbSMarc-André Lureau return (void *)obj + lprop->offset; 17099941d37bSMarc-André Lureau } else { 17109941d37bSMarc-André Lureau return lprop->targetp; 17119941d37bSMarc-André Lureau } 17129941d37bSMarc-André Lureau } 17139941d37bSMarc-André Lureau 1714d7bce999SEric Blake static void object_get_link_property(Object *obj, Visitor *v, 1715d7bce999SEric Blake const char *name, void *opaque, 1716d7bce999SEric Blake Error **errp) 171757c9fafeSAnthony Liguori { 17189561fda8SStefan Hajnoczi LinkProperty *lprop = opaque; 17199941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, lprop); 1720ddfb0baaSMarkus Armbruster char *path; 172157c9fafeSAnthony Liguori 172236854207SMarc-André Lureau if (*targetp) { 172336854207SMarc-André Lureau path = object_get_canonical_path(*targetp); 172451e72bc1SEric Blake visit_type_str(v, name, &path, errp); 172557c9fafeSAnthony Liguori g_free(path); 172657c9fafeSAnthony Liguori } else { 1727ddfb0baaSMarkus Armbruster path = (char *)""; 172851e72bc1SEric Blake visit_type_str(v, name, &path, errp); 172957c9fafeSAnthony Liguori } 173057c9fafeSAnthony Liguori } 173157c9fafeSAnthony Liguori 1732f5ec6704SStefan Hajnoczi /* 1733f5ec6704SStefan Hajnoczi * object_resolve_link: 1734f5ec6704SStefan Hajnoczi * 1735f5ec6704SStefan Hajnoczi * Lookup an object and ensure its type matches the link property type. This 1736f5ec6704SStefan Hajnoczi * is similar to object_resolve_path() except type verification against the 1737f5ec6704SStefan Hajnoczi * link property is performed. 1738f5ec6704SStefan Hajnoczi * 1739f5ec6704SStefan Hajnoczi * Returns: The matched object or NULL on path lookup failures. 1740f5ec6704SStefan Hajnoczi */ 1741f5ec6704SStefan Hajnoczi static Object *object_resolve_link(Object *obj, const char *name, 1742f5ec6704SStefan Hajnoczi const char *path, Error **errp) 1743f5ec6704SStefan Hajnoczi { 1744f5ec6704SStefan Hajnoczi const char *type; 1745ddfb0baaSMarkus Armbruster char *target_type; 1746f5ec6704SStefan Hajnoczi bool ambiguous = false; 1747f5ec6704SStefan Hajnoczi Object *target; 1748f5ec6704SStefan Hajnoczi 1749f5ec6704SStefan Hajnoczi /* Go from link<FOO> to FOO. */ 1750f5ec6704SStefan Hajnoczi type = object_property_get_type(obj, name, NULL); 1751f5ec6704SStefan Hajnoczi target_type = g_strndup(&type[5], strlen(type) - 6); 1752f5ec6704SStefan Hajnoczi target = object_resolve_path_type(path, target_type, &ambiguous); 1753f5ec6704SStefan Hajnoczi 1754f5ec6704SStefan Hajnoczi if (ambiguous) { 1755455b0fdeSEric Blake error_setg(errp, "Path '%s' does not uniquely identify an object", 1756455b0fdeSEric Blake path); 1757f5ec6704SStefan Hajnoczi } else if (!target) { 1758f5ec6704SStefan Hajnoczi target = object_resolve_path(path, &ambiguous); 1759f5ec6704SStefan Hajnoczi if (target || ambiguous) { 1760c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type); 1761f5ec6704SStefan Hajnoczi } else { 176275158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 176375158ebbSMarkus Armbruster "Device '%s' not found", path); 1764f5ec6704SStefan Hajnoczi } 1765f5ec6704SStefan Hajnoczi target = NULL; 1766f5ec6704SStefan Hajnoczi } 1767f5ec6704SStefan Hajnoczi g_free(target_type); 1768f5ec6704SStefan Hajnoczi 1769f5ec6704SStefan Hajnoczi return target; 1770f5ec6704SStefan Hajnoczi } 1771f5ec6704SStefan Hajnoczi 1772d7bce999SEric Blake static void object_set_link_property(Object *obj, Visitor *v, 1773d7bce999SEric Blake const char *name, void *opaque, 1774d7bce999SEric Blake Error **errp) 177557c9fafeSAnthony Liguori { 1776c6aed983SStefan Hajnoczi Error *local_err = NULL; 17779561fda8SStefan Hajnoczi LinkProperty *prop = opaque; 17789941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, prop); 177936854207SMarc-André Lureau Object *old_target = *targetp; 1780c6aed983SStefan Hajnoczi Object *new_target = NULL; 1781c6aed983SStefan Hajnoczi char *path = NULL; 178257c9fafeSAnthony Liguori 178351e72bc1SEric Blake visit_type_str(v, name, &path, &local_err); 178457c9fafeSAnthony Liguori 1785c6aed983SStefan Hajnoczi if (!local_err && strcmp(path, "") != 0) { 1786c6aed983SStefan Hajnoczi new_target = object_resolve_link(obj, name, path, &local_err); 178711e35bfdSPaolo Bonzini } 178857c9fafeSAnthony Liguori 178957c9fafeSAnthony Liguori g_free(path); 1790c6aed983SStefan Hajnoczi if (local_err) { 1791c6aed983SStefan Hajnoczi error_propagate(errp, local_err); 1792c6aed983SStefan Hajnoczi return; 1793c6aed983SStefan Hajnoczi } 1794f0cdc966SAlexander Barabash 179539f72ef9SStefan Hajnoczi prop->check(obj, name, new_target, &local_err); 179639f72ef9SStefan Hajnoczi if (local_err) { 179739f72ef9SStefan Hajnoczi error_propagate(errp, local_err); 179839f72ef9SStefan Hajnoczi return; 179939f72ef9SStefan Hajnoczi } 180039f72ef9SStefan Hajnoczi 180136854207SMarc-André Lureau *targetp = new_target; 18028770bafdSMarc-André Lureau if (prop->flags & OBJ_PROP_LINK_STRONG) { 1803265b578cSMarc-André Lureau object_ref(new_target); 1804f0cdc966SAlexander Barabash object_unref(old_target); 1805f0cdc966SAlexander Barabash } 1806265b578cSMarc-André Lureau } 180757c9fafeSAnthony Liguori 1808ddfb0baaSMarkus Armbruster static Object *object_resolve_link_property(Object *parent, void *opaque, 1809ddfb0baaSMarkus Armbruster const char *part) 181064607d08SPaolo Bonzini { 181164607d08SPaolo Bonzini LinkProperty *lprop = opaque; 181264607d08SPaolo Bonzini 18139941d37bSMarc-André Lureau return *object_link_get_targetp(parent, lprop); 181464607d08SPaolo Bonzini } 181564607d08SPaolo Bonzini 18169561fda8SStefan Hajnoczi static void object_release_link_property(Object *obj, const char *name, 18179561fda8SStefan Hajnoczi void *opaque) 18189561fda8SStefan Hajnoczi { 18199561fda8SStefan Hajnoczi LinkProperty *prop = opaque; 18209941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, prop); 18219561fda8SStefan Hajnoczi 18229941d37bSMarc-André Lureau if ((prop->flags & OBJ_PROP_LINK_STRONG) && *targetp) { 18239941d37bSMarc-André Lureau object_unref(*targetp); 18249561fda8SStefan Hajnoczi } 1825840ecdfbSMarc-André Lureau if (!(prop->flags & OBJ_PROP_LINK_CLASS)) { 18269561fda8SStefan Hajnoczi g_free(prop); 18279561fda8SStefan Hajnoczi } 1828840ecdfbSMarc-André Lureau } 18299561fda8SStefan Hajnoczi 183070251887SMarkus Armbruster static ObjectProperty * 183170251887SMarkus Armbruster object_add_link_prop(Object *obj, const char *name, 18324a8d5798SMarc-André Lureau const char *type, void *ptr, 18338f5d58efSIgor Mammedov void (*check)(const Object *, const char *, 183439f72ef9SStefan Hajnoczi Object *, Error **), 1835d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags) 183657c9fafeSAnthony Liguori { 18379561fda8SStefan Hajnoczi LinkProperty *prop = g_malloc(sizeof(*prop)); 183870251887SMarkus Armbruster g_autofree char *full_type = NULL; 183964607d08SPaolo Bonzini ObjectProperty *op; 184057c9fafeSAnthony Liguori 18414a8d5798SMarc-André Lureau if (flags & OBJ_PROP_LINK_DIRECT) { 18424a8d5798SMarc-André Lureau prop->target = ptr; 18434a8d5798SMarc-André Lureau } else { 18444a8d5798SMarc-André Lureau prop->targetp = ptr; 18454a8d5798SMarc-André Lureau } 184639f72ef9SStefan Hajnoczi prop->check = check; 18479561fda8SStefan Hajnoczi prop->flags = flags; 18489561fda8SStefan Hajnoczi 184957c9fafeSAnthony Liguori full_type = g_strdup_printf("link<%s>", type); 185057c9fafeSAnthony Liguori 185164607d08SPaolo Bonzini op = object_property_add(obj, name, full_type, 185257c9fafeSAnthony Liguori object_get_link_property, 185339f72ef9SStefan Hajnoczi check ? object_set_link_property : NULL, 18549561fda8SStefan Hajnoczi object_release_link_property, 1855d2623129SMarkus Armbruster prop); 185664607d08SPaolo Bonzini op->resolve = object_resolve_link_property; 185770251887SMarkus Armbruster return op; 185857c9fafeSAnthony Liguori } 185957c9fafeSAnthony Liguori 186070251887SMarkus Armbruster ObjectProperty * 186170251887SMarkus Armbruster object_property_add_link(Object *obj, const char *name, 18624a8d5798SMarc-André Lureau const char *type, Object **targetp, 18634a8d5798SMarc-André Lureau void (*check)(const Object *, const char *, 18644a8d5798SMarc-André Lureau Object *, Error **), 1865d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags) 18664a8d5798SMarc-André Lureau { 1867d2623129SMarkus Armbruster return object_add_link_prop(obj, name, type, targetp, check, flags); 18684a8d5798SMarc-André Lureau } 18694a8d5798SMarc-André Lureau 1870840ecdfbSMarc-André Lureau ObjectProperty * 1871840ecdfbSMarc-André Lureau object_class_property_add_link(ObjectClass *oc, 1872840ecdfbSMarc-André Lureau const char *name, 1873840ecdfbSMarc-André Lureau const char *type, ptrdiff_t offset, 1874840ecdfbSMarc-André Lureau void (*check)(const Object *obj, const char *name, 1875840ecdfbSMarc-André Lureau Object *val, Error **errp), 1876d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags) 1877840ecdfbSMarc-André Lureau { 1878840ecdfbSMarc-André Lureau LinkProperty *prop = g_new0(LinkProperty, 1); 1879ddfb0baaSMarkus Armbruster char *full_type; 1880840ecdfbSMarc-André Lureau ObjectProperty *op; 1881840ecdfbSMarc-André Lureau 1882840ecdfbSMarc-André Lureau prop->offset = offset; 1883840ecdfbSMarc-André Lureau prop->check = check; 1884840ecdfbSMarc-André Lureau prop->flags = flags | OBJ_PROP_LINK_CLASS; 1885840ecdfbSMarc-André Lureau 1886840ecdfbSMarc-André Lureau full_type = g_strdup_printf("link<%s>", type); 1887840ecdfbSMarc-André Lureau 1888840ecdfbSMarc-André Lureau op = object_class_property_add(oc, name, full_type, 1889840ecdfbSMarc-André Lureau object_get_link_property, 1890840ecdfbSMarc-André Lureau check ? object_set_link_property : NULL, 1891840ecdfbSMarc-André Lureau object_release_link_property, 1892d2623129SMarkus Armbruster prop); 1893840ecdfbSMarc-André Lureau 1894840ecdfbSMarc-André Lureau op->resolve = object_resolve_link_property; 1895840ecdfbSMarc-André Lureau 1896840ecdfbSMarc-André Lureau g_free(full_type); 1897840ecdfbSMarc-André Lureau return op; 1898840ecdfbSMarc-André Lureau } 1899840ecdfbSMarc-André Lureau 190070251887SMarkus Armbruster ObjectProperty * 190170251887SMarkus Armbruster object_property_add_const_link(Object *obj, const char *name, 1902d2623129SMarkus Armbruster Object *target) 1903fb9e7e33SPaolo Bonzini { 190470251887SMarkus Armbruster return object_add_link_prop(obj, name, 190570251887SMarkus Armbruster object_get_typename(target), target, 1906d2623129SMarkus Armbruster NULL, OBJ_PROP_LINK_DIRECT); 1907fb9e7e33SPaolo Bonzini } 1908fb9e7e33SPaolo Bonzini 1909e8512dfaSMarkus Armbruster char *object_get_canonical_path_component(const Object *obj) 191057c9fafeSAnthony Liguori { 191157c9fafeSAnthony Liguori ObjectProperty *prop = NULL; 1912b604a854SPavel Fedin GHashTableIter iter; 191357c9fafeSAnthony Liguori 1914770dec26SPaolo Bonzini if (obj->parent == NULL) { 1915770dec26SPaolo Bonzini return NULL; 1916770dec26SPaolo Bonzini } 191757c9fafeSAnthony Liguori 1918b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->parent->properties); 1919b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 19205d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 192157c9fafeSAnthony Liguori continue; 192257c9fafeSAnthony Liguori } 192357c9fafeSAnthony Liguori 192457c9fafeSAnthony Liguori if (prop->opaque == obj) { 192511f590b1SStefan Hajnoczi return g_strdup(prop->name); 192657c9fafeSAnthony Liguori } 192757c9fafeSAnthony Liguori } 192857c9fafeSAnthony Liguori 192911f590b1SStefan Hajnoczi /* obj had a parent but was not a child, should never happen */ 193011f590b1SStefan Hajnoczi g_assert_not_reached(); 193111f590b1SStefan Hajnoczi return NULL; 193211f590b1SStefan Hajnoczi } 193311f590b1SStefan Hajnoczi 1934e8512dfaSMarkus Armbruster char *object_get_canonical_path(const Object *obj) 193511f590b1SStefan Hajnoczi { 193611f590b1SStefan Hajnoczi Object *root = object_get_root(); 193711f590b1SStefan Hajnoczi char *newpath, *path = NULL; 193811f590b1SStefan Hajnoczi 1939e40077fdSPaolo Bonzini if (obj == root) { 1940e40077fdSPaolo Bonzini return g_strdup("/"); 1941e40077fdSPaolo Bonzini } 1942e40077fdSPaolo Bonzini 1943e40077fdSPaolo Bonzini do { 194411f590b1SStefan Hajnoczi char *component = object_get_canonical_path_component(obj); 194511f590b1SStefan Hajnoczi 1946e40077fdSPaolo Bonzini if (!component) { 1947e40077fdSPaolo Bonzini /* A canonical path must be complete, so discard what was 1948e40077fdSPaolo Bonzini * collected so far. 1949e40077fdSPaolo Bonzini */ 1950e40077fdSPaolo Bonzini g_free(path); 1951e40077fdSPaolo Bonzini return NULL; 1952e40077fdSPaolo Bonzini } 1953e40077fdSPaolo Bonzini 1954e40077fdSPaolo Bonzini newpath = g_strdup_printf("/%s%s", component, path ? path : ""); 1955e40077fdSPaolo Bonzini g_free(path); 195611f590b1SStefan Hajnoczi g_free(component); 195711f590b1SStefan Hajnoczi path = newpath; 195857c9fafeSAnthony Liguori obj = obj->parent; 1959e40077fdSPaolo Bonzini } while (obj != root); 196057c9fafeSAnthony Liguori 1961e40077fdSPaolo Bonzini return path; 196257c9fafeSAnthony Liguori } 196357c9fafeSAnthony Liguori 1964ddfb0baaSMarkus Armbruster Object *object_resolve_path_component(Object *parent, const char *part) 1965a612b2a6SPaolo Bonzini { 196689bfe000SPaolo Bonzini ObjectProperty *prop = object_property_find(parent, part, NULL); 1967a612b2a6SPaolo Bonzini if (prop == NULL) { 1968a612b2a6SPaolo Bonzini return NULL; 1969a612b2a6SPaolo Bonzini } 1970a612b2a6SPaolo Bonzini 197164607d08SPaolo Bonzini if (prop->resolve) { 197264607d08SPaolo Bonzini return prop->resolve(parent, prop->opaque, part); 1973a612b2a6SPaolo Bonzini } else { 1974a612b2a6SPaolo Bonzini return NULL; 1975a612b2a6SPaolo Bonzini } 1976a612b2a6SPaolo Bonzini } 1977a612b2a6SPaolo Bonzini 197857c9fafeSAnthony Liguori static Object *object_resolve_abs_path(Object *parent, 1979ddfb0baaSMarkus Armbruster char **parts, 1980ad195c8fSMasahiro Yamada const char *typename) 198157c9fafeSAnthony Liguori { 198257c9fafeSAnthony Liguori Object *child; 198357c9fafeSAnthony Liguori 1984ad195c8fSMasahiro Yamada if (*parts == NULL) { 198502fe2db6SPaolo Bonzini return object_dynamic_cast(parent, typename); 198657c9fafeSAnthony Liguori } 198757c9fafeSAnthony Liguori 1988ad195c8fSMasahiro Yamada if (strcmp(*parts, "") == 0) { 1989ad195c8fSMasahiro Yamada return object_resolve_abs_path(parent, parts + 1, typename); 199057c9fafeSAnthony Liguori } 199157c9fafeSAnthony Liguori 1992ad195c8fSMasahiro Yamada child = object_resolve_path_component(parent, *parts); 199357c9fafeSAnthony Liguori if (!child) { 199457c9fafeSAnthony Liguori return NULL; 199557c9fafeSAnthony Liguori } 199657c9fafeSAnthony Liguori 1997ad195c8fSMasahiro Yamada return object_resolve_abs_path(child, parts + 1, typename); 199857c9fafeSAnthony Liguori } 199957c9fafeSAnthony Liguori 200057c9fafeSAnthony Liguori static Object *object_resolve_partial_path(Object *parent, 2001ddfb0baaSMarkus Armbruster char **parts, 200202fe2db6SPaolo Bonzini const char *typename, 200357c9fafeSAnthony Liguori bool *ambiguous) 200457c9fafeSAnthony Liguori { 200557c9fafeSAnthony Liguori Object *obj; 2006b604a854SPavel Fedin GHashTableIter iter; 200757c9fafeSAnthony Liguori ObjectProperty *prop; 200857c9fafeSAnthony Liguori 2009ad195c8fSMasahiro Yamada obj = object_resolve_abs_path(parent, parts, typename); 201057c9fafeSAnthony Liguori 2011b604a854SPavel Fedin g_hash_table_iter_init(&iter, parent->properties); 2012b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 201357c9fafeSAnthony Liguori Object *found; 201457c9fafeSAnthony Liguori 20155d9d3f47SAndreas Färber if (!object_property_is_child(prop)) { 201657c9fafeSAnthony Liguori continue; 201757c9fafeSAnthony Liguori } 201857c9fafeSAnthony Liguori 201902fe2db6SPaolo Bonzini found = object_resolve_partial_path(prop->opaque, parts, 202002fe2db6SPaolo Bonzini typename, ambiguous); 202157c9fafeSAnthony Liguori if (found) { 202257c9fafeSAnthony Liguori if (obj) { 202357c9fafeSAnthony Liguori *ambiguous = true; 202457c9fafeSAnthony Liguori return NULL; 202557c9fafeSAnthony Liguori } 202657c9fafeSAnthony Liguori obj = found; 202757c9fafeSAnthony Liguori } 202857c9fafeSAnthony Liguori 2029ebcc479eSEduardo Habkost if (*ambiguous) { 203057c9fafeSAnthony Liguori return NULL; 203157c9fafeSAnthony Liguori } 203257c9fafeSAnthony Liguori } 203357c9fafeSAnthony Liguori 203457c9fafeSAnthony Liguori return obj; 203557c9fafeSAnthony Liguori } 203657c9fafeSAnthony Liguori 203702fe2db6SPaolo Bonzini Object *object_resolve_path_type(const char *path, const char *typename, 2038ebcc479eSEduardo Habkost bool *ambiguousp) 203957c9fafeSAnthony Liguori { 204057c9fafeSAnthony Liguori Object *obj; 2041ddfb0baaSMarkus Armbruster char **parts; 204257c9fafeSAnthony Liguori 204357c9fafeSAnthony Liguori parts = g_strsplit(path, "/", 0); 20442e1103f6SPaolo Bonzini assert(parts); 204557c9fafeSAnthony Liguori 20462e1103f6SPaolo Bonzini if (parts[0] == NULL || strcmp(parts[0], "") != 0) { 2047ebcc479eSEduardo Habkost bool ambiguous = false; 204802fe2db6SPaolo Bonzini obj = object_resolve_partial_path(object_get_root(), parts, 2049ebcc479eSEduardo Habkost typename, &ambiguous); 2050ebcc479eSEduardo Habkost if (ambiguousp) { 2051ebcc479eSEduardo Habkost *ambiguousp = ambiguous; 2052ebcc479eSEduardo Habkost } 205357c9fafeSAnthony Liguori } else { 2054ad195c8fSMasahiro Yamada obj = object_resolve_abs_path(object_get_root(), parts + 1, typename); 205557c9fafeSAnthony Liguori } 205657c9fafeSAnthony Liguori 205757c9fafeSAnthony Liguori g_strfreev(parts); 205857c9fafeSAnthony Liguori 205957c9fafeSAnthony Liguori return obj; 206057c9fafeSAnthony Liguori } 206157c9fafeSAnthony Liguori 206202fe2db6SPaolo Bonzini Object *object_resolve_path(const char *path, bool *ambiguous) 206302fe2db6SPaolo Bonzini { 206402fe2db6SPaolo Bonzini return object_resolve_path_type(path, TYPE_OBJECT, ambiguous); 206502fe2db6SPaolo Bonzini } 206602fe2db6SPaolo Bonzini 206757c9fafeSAnthony Liguori typedef struct StringProperty 206857c9fafeSAnthony Liguori { 206957c9fafeSAnthony Liguori char *(*get)(Object *, Error **); 207057c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **); 207157c9fafeSAnthony Liguori } StringProperty; 207257c9fafeSAnthony Liguori 2073d7bce999SEric Blake static void property_get_str(Object *obj, Visitor *v, const char *name, 2074d7bce999SEric Blake void *opaque, Error **errp) 207557c9fafeSAnthony Liguori { 207657c9fafeSAnthony Liguori StringProperty *prop = opaque; 207757c9fafeSAnthony Liguori char *value; 2078e1c8237dSMarkus Armbruster Error *err = NULL; 207957c9fafeSAnthony Liguori 2080e1c8237dSMarkus Armbruster value = prop->get(obj, &err); 2081e1c8237dSMarkus Armbruster if (err) { 2082e1c8237dSMarkus Armbruster error_propagate(errp, err); 2083e1c8237dSMarkus Armbruster return; 2084e1c8237dSMarkus Armbruster } 2085e1c8237dSMarkus Armbruster 208651e72bc1SEric Blake visit_type_str(v, name, &value, errp); 208757c9fafeSAnthony Liguori g_free(value); 208857c9fafeSAnthony Liguori } 208957c9fafeSAnthony Liguori 2090d7bce999SEric Blake static void property_set_str(Object *obj, Visitor *v, const char *name, 2091d7bce999SEric Blake void *opaque, Error **errp) 209257c9fafeSAnthony Liguori { 209357c9fafeSAnthony Liguori StringProperty *prop = opaque; 209457c9fafeSAnthony Liguori char *value; 209557c9fafeSAnthony Liguori Error *local_err = NULL; 209657c9fafeSAnthony Liguori 209762a35aaaSMarkus Armbruster if (!visit_type_str(v, name, &value, &local_err)) { 209857c9fafeSAnthony Liguori error_propagate(errp, local_err); 209957c9fafeSAnthony Liguori return; 210057c9fafeSAnthony Liguori } 210157c9fafeSAnthony Liguori 210257c9fafeSAnthony Liguori prop->set(obj, value, errp); 210357c9fafeSAnthony Liguori g_free(value); 210457c9fafeSAnthony Liguori } 210557c9fafeSAnthony Liguori 21067b7b7d18SPaolo Bonzini static void property_release_str(Object *obj, const char *name, 210757c9fafeSAnthony Liguori void *opaque) 210857c9fafeSAnthony Liguori { 210957c9fafeSAnthony Liguori StringProperty *prop = opaque; 211057c9fafeSAnthony Liguori g_free(prop); 211157c9fafeSAnthony Liguori } 211257c9fafeSAnthony Liguori 211370251887SMarkus Armbruster ObjectProperty * 211470251887SMarkus Armbruster object_property_add_str(Object *obj, const char *name, 211557c9fafeSAnthony Liguori char *(*get)(Object *, Error **), 2116d2623129SMarkus Armbruster void (*set)(Object *, const char *, Error **)) 211757c9fafeSAnthony Liguori { 211857c9fafeSAnthony Liguori StringProperty *prop = g_malloc0(sizeof(*prop)); 211957c9fafeSAnthony Liguori 212057c9fafeSAnthony Liguori prop->get = get; 212157c9fafeSAnthony Liguori prop->set = set; 212257c9fafeSAnthony Liguori 2123d2623129SMarkus Armbruster return object_property_add(obj, name, "string", 21247b7b7d18SPaolo Bonzini get ? property_get_str : NULL, 21257b7b7d18SPaolo Bonzini set ? property_set_str : NULL, 21267b7b7d18SPaolo Bonzini property_release_str, 2127d2623129SMarkus Armbruster prop); 212857c9fafeSAnthony Liguori } 2129745549c8SPaolo Bonzini 2130a3a16211SMarc-André Lureau ObjectProperty * 2131a3a16211SMarc-André Lureau object_class_property_add_str(ObjectClass *klass, const char *name, 213216bf7f52SDaniel P. Berrange char *(*get)(Object *, Error **), 213316bf7f52SDaniel P. Berrange void (*set)(Object *, const char *, 2134d2623129SMarkus Armbruster Error **)) 213516bf7f52SDaniel P. Berrange { 213616bf7f52SDaniel P. Berrange StringProperty *prop = g_malloc0(sizeof(*prop)); 213716bf7f52SDaniel P. Berrange 213816bf7f52SDaniel P. Berrange prop->get = get; 213916bf7f52SDaniel P. Berrange prop->set = set; 214016bf7f52SDaniel P. Berrange 2141d2623129SMarkus Armbruster return object_class_property_add(klass, name, "string", 214216bf7f52SDaniel P. Berrange get ? property_get_str : NULL, 214316bf7f52SDaniel P. Berrange set ? property_set_str : NULL, 2144fc4fe712SMarc-André Lureau NULL, 2145d2623129SMarkus Armbruster prop); 214616bf7f52SDaniel P. Berrange } 214716bf7f52SDaniel P. Berrange 21480e558843SAnthony Liguori typedef struct BoolProperty 21490e558843SAnthony Liguori { 21500e558843SAnthony Liguori bool (*get)(Object *, Error **); 21510e558843SAnthony Liguori void (*set)(Object *, bool, Error **); 21520e558843SAnthony Liguori } BoolProperty; 21530e558843SAnthony Liguori 2154d7bce999SEric Blake static void property_get_bool(Object *obj, Visitor *v, const char *name, 2155d7bce999SEric Blake void *opaque, Error **errp) 21560e558843SAnthony Liguori { 21570e558843SAnthony Liguori BoolProperty *prop = opaque; 21580e558843SAnthony Liguori bool value; 21594715d42eSMarkus Armbruster Error *err = NULL; 21600e558843SAnthony Liguori 21614715d42eSMarkus Armbruster value = prop->get(obj, &err); 21624715d42eSMarkus Armbruster if (err) { 21634715d42eSMarkus Armbruster error_propagate(errp, err); 21644715d42eSMarkus Armbruster return; 21654715d42eSMarkus Armbruster } 21664715d42eSMarkus Armbruster 216751e72bc1SEric Blake visit_type_bool(v, name, &value, errp); 21680e558843SAnthony Liguori } 21690e558843SAnthony Liguori 2170d7bce999SEric Blake static void property_set_bool(Object *obj, Visitor *v, const char *name, 2171d7bce999SEric Blake void *opaque, Error **errp) 21720e558843SAnthony Liguori { 21730e558843SAnthony Liguori BoolProperty *prop = opaque; 21740e558843SAnthony Liguori bool value; 21750e558843SAnthony Liguori Error *local_err = NULL; 21760e558843SAnthony Liguori 217762a35aaaSMarkus Armbruster if (!visit_type_bool(v, name, &value, &local_err)) { 21780e558843SAnthony Liguori error_propagate(errp, local_err); 21790e558843SAnthony Liguori return; 21800e558843SAnthony Liguori } 21810e558843SAnthony Liguori 21820e558843SAnthony Liguori prop->set(obj, value, errp); 21830e558843SAnthony Liguori } 21840e558843SAnthony Liguori 21850e558843SAnthony Liguori static void property_release_bool(Object *obj, const char *name, 21860e558843SAnthony Liguori void *opaque) 21870e558843SAnthony Liguori { 21880e558843SAnthony Liguori BoolProperty *prop = opaque; 21890e558843SAnthony Liguori g_free(prop); 21900e558843SAnthony Liguori } 21910e558843SAnthony Liguori 219270251887SMarkus Armbruster ObjectProperty * 219370251887SMarkus Armbruster object_property_add_bool(Object *obj, const char *name, 21940e558843SAnthony Liguori bool (*get)(Object *, Error **), 2195d2623129SMarkus Armbruster void (*set)(Object *, bool, Error **)) 21960e558843SAnthony Liguori { 21970e558843SAnthony Liguori BoolProperty *prop = g_malloc0(sizeof(*prop)); 21980e558843SAnthony Liguori 21990e558843SAnthony Liguori prop->get = get; 22000e558843SAnthony Liguori prop->set = set; 22010e558843SAnthony Liguori 2202d2623129SMarkus Armbruster return object_property_add(obj, name, "bool", 22030e558843SAnthony Liguori get ? property_get_bool : NULL, 22040e558843SAnthony Liguori set ? property_set_bool : NULL, 22050e558843SAnthony Liguori property_release_bool, 2206d2623129SMarkus Armbruster prop); 22070e558843SAnthony Liguori } 22080e558843SAnthony Liguori 2209a3a16211SMarc-André Lureau ObjectProperty * 2210a3a16211SMarc-André Lureau object_class_property_add_bool(ObjectClass *klass, const char *name, 221116bf7f52SDaniel P. Berrange bool (*get)(Object *, Error **), 2212d2623129SMarkus Armbruster void (*set)(Object *, bool, Error **)) 221316bf7f52SDaniel P. Berrange { 221416bf7f52SDaniel P. Berrange BoolProperty *prop = g_malloc0(sizeof(*prop)); 221516bf7f52SDaniel P. Berrange 221616bf7f52SDaniel P. Berrange prop->get = get; 221716bf7f52SDaniel P. Berrange prop->set = set; 221816bf7f52SDaniel P. Berrange 2219d2623129SMarkus Armbruster return object_class_property_add(klass, name, "bool", 222016bf7f52SDaniel P. Berrange get ? property_get_bool : NULL, 222116bf7f52SDaniel P. Berrange set ? property_set_bool : NULL, 2222fc4fe712SMarc-André Lureau NULL, 2223d2623129SMarkus Armbruster prop); 222416bf7f52SDaniel P. Berrange } 222516bf7f52SDaniel P. Berrange 2226d7bce999SEric Blake static void property_get_enum(Object *obj, Visitor *v, const char *name, 2227d7bce999SEric Blake void *opaque, Error **errp) 2228a8e3fbedSDaniel P. Berrange { 2229a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 2230a8e3fbedSDaniel P. Berrange int value; 22314715d42eSMarkus Armbruster Error *err = NULL; 2232a8e3fbedSDaniel P. Berrange 22334715d42eSMarkus Armbruster value = prop->get(obj, &err); 22344715d42eSMarkus Armbruster if (err) { 22354715d42eSMarkus Armbruster error_propagate(errp, err); 22364715d42eSMarkus Armbruster return; 22374715d42eSMarkus Armbruster } 22384715d42eSMarkus Armbruster 2239f7abe0ecSMarc-André Lureau visit_type_enum(v, name, &value, prop->lookup, errp); 2240a8e3fbedSDaniel P. Berrange } 2241a8e3fbedSDaniel P. Berrange 2242d7bce999SEric Blake static void property_set_enum(Object *obj, Visitor *v, const char *name, 2243d7bce999SEric Blake void *opaque, Error **errp) 2244a8e3fbedSDaniel P. Berrange { 2245a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 2246a8e3fbedSDaniel P. Berrange int value; 22474715d42eSMarkus Armbruster Error *err = NULL; 2248a8e3fbedSDaniel P. Berrange 224962a35aaaSMarkus Armbruster if (!visit_type_enum(v, name, &value, prop->lookup, &err)) { 22504715d42eSMarkus Armbruster error_propagate(errp, err); 22514715d42eSMarkus Armbruster return; 22524715d42eSMarkus Armbruster } 2253a8e3fbedSDaniel P. Berrange prop->set(obj, value, errp); 2254a8e3fbedSDaniel P. Berrange } 2255a8e3fbedSDaniel P. Berrange 2256a8e3fbedSDaniel P. Berrange static void property_release_enum(Object *obj, const char *name, 2257a8e3fbedSDaniel P. Berrange void *opaque) 2258a8e3fbedSDaniel P. Berrange { 2259a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque; 2260a8e3fbedSDaniel P. Berrange g_free(prop); 2261a8e3fbedSDaniel P. Berrange } 2262a8e3fbedSDaniel P. Berrange 226370251887SMarkus Armbruster ObjectProperty * 226470251887SMarkus Armbruster object_property_add_enum(Object *obj, const char *name, 2265a8e3fbedSDaniel P. Berrange const char *typename, 2266f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, 2267a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **), 2268d2623129SMarkus Armbruster void (*set)(Object *, int, Error **)) 2269a8e3fbedSDaniel P. Berrange { 2270a8e3fbedSDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop)); 2271a8e3fbedSDaniel P. Berrange 2272f7abe0ecSMarc-André Lureau prop->lookup = lookup; 2273a8e3fbedSDaniel P. Berrange prop->get = get; 2274a8e3fbedSDaniel P. Berrange prop->set = set; 2275a8e3fbedSDaniel P. Berrange 2276d2623129SMarkus Armbruster return object_property_add(obj, name, typename, 2277a8e3fbedSDaniel P. Berrange get ? property_get_enum : NULL, 2278a8e3fbedSDaniel P. Berrange set ? property_set_enum : NULL, 2279a8e3fbedSDaniel P. Berrange property_release_enum, 2280d2623129SMarkus Armbruster prop); 2281a8e3fbedSDaniel P. Berrange } 2282a8e3fbedSDaniel P. Berrange 2283a3a16211SMarc-André Lureau ObjectProperty * 2284a3a16211SMarc-André Lureau object_class_property_add_enum(ObjectClass *klass, const char *name, 228516bf7f52SDaniel P. Berrange const char *typename, 2286f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, 228716bf7f52SDaniel P. Berrange int (*get)(Object *, Error **), 2288d2623129SMarkus Armbruster void (*set)(Object *, int, Error **)) 228916bf7f52SDaniel P. Berrange { 229016bf7f52SDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop)); 229116bf7f52SDaniel P. Berrange 2292f7abe0ecSMarc-André Lureau prop->lookup = lookup; 229316bf7f52SDaniel P. Berrange prop->get = get; 229416bf7f52SDaniel P. Berrange prop->set = set; 229516bf7f52SDaniel P. Berrange 2296d2623129SMarkus Armbruster return object_class_property_add(klass, name, typename, 229716bf7f52SDaniel P. Berrange get ? property_get_enum : NULL, 229816bf7f52SDaniel P. Berrange set ? property_set_enum : NULL, 2299fc4fe712SMarc-André Lureau NULL, 2300d2623129SMarkus Armbruster prop); 230116bf7f52SDaniel P. Berrange } 230216bf7f52SDaniel P. Berrange 23038e099d14SDavid Gibson typedef struct TMProperty { 23048e099d14SDavid Gibson void (*get)(Object *, struct tm *, Error **); 23058e099d14SDavid Gibson } TMProperty; 23068e099d14SDavid Gibson 2307d7bce999SEric Blake static void property_get_tm(Object *obj, Visitor *v, const char *name, 2308d7bce999SEric Blake void *opaque, Error **errp) 23098e099d14SDavid Gibson { 23108e099d14SDavid Gibson TMProperty *prop = opaque; 23118e099d14SDavid Gibson Error *err = NULL; 23128e099d14SDavid Gibson struct tm value; 23138e099d14SDavid Gibson 23148e099d14SDavid Gibson prop->get(obj, &value, &err); 23158e099d14SDavid Gibson if (err) { 23168e099d14SDavid Gibson goto out; 23178e099d14SDavid Gibson } 23188e099d14SDavid Gibson 231962a35aaaSMarkus Armbruster if (!visit_start_struct(v, name, NULL, 0, &err)) { 23208e099d14SDavid Gibson goto out; 23218e099d14SDavid Gibson } 232262a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_year", &value.tm_year, &err)) { 23238e099d14SDavid Gibson goto out_end; 23248e099d14SDavid Gibson } 232562a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_mon", &value.tm_mon, &err)) { 23268e099d14SDavid Gibson goto out_end; 23278e099d14SDavid Gibson } 232862a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_mday", &value.tm_mday, &err)) { 23298e099d14SDavid Gibson goto out_end; 23308e099d14SDavid Gibson } 233162a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_hour", &value.tm_hour, &err)) { 23328e099d14SDavid Gibson goto out_end; 23338e099d14SDavid Gibson } 233462a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_min", &value.tm_min, &err)) { 23358e099d14SDavid Gibson goto out_end; 23368e099d14SDavid Gibson } 233762a35aaaSMarkus Armbruster if (!visit_type_int32(v, "tm_sec", &value.tm_sec, &err)) { 23388e099d14SDavid Gibson goto out_end; 23398e099d14SDavid Gibson } 234015c2f669SEric Blake visit_check_struct(v, &err); 23418e099d14SDavid Gibson out_end: 23421158bb2aSEric Blake visit_end_struct(v, NULL); 23438e099d14SDavid Gibson out: 23448e099d14SDavid Gibson error_propagate(errp, err); 23458e099d14SDavid Gibson 23468e099d14SDavid Gibson } 23478e099d14SDavid Gibson 23488e099d14SDavid Gibson static void property_release_tm(Object *obj, const char *name, 23498e099d14SDavid Gibson void *opaque) 23508e099d14SDavid Gibson { 23518e099d14SDavid Gibson TMProperty *prop = opaque; 23528e099d14SDavid Gibson g_free(prop); 23538e099d14SDavid Gibson } 23548e099d14SDavid Gibson 235570251887SMarkus Armbruster ObjectProperty * 235670251887SMarkus Armbruster object_property_add_tm(Object *obj, const char *name, 2357d2623129SMarkus Armbruster void (*get)(Object *, struct tm *, Error **)) 23588e099d14SDavid Gibson { 23598e099d14SDavid Gibson TMProperty *prop = g_malloc0(sizeof(*prop)); 23608e099d14SDavid Gibson 23618e099d14SDavid Gibson prop->get = get; 23628e099d14SDavid Gibson 2363d2623129SMarkus Armbruster return object_property_add(obj, name, "struct tm", 23648e099d14SDavid Gibson get ? property_get_tm : NULL, NULL, 23658e099d14SDavid Gibson property_release_tm, 2366d2623129SMarkus Armbruster prop); 23678e099d14SDavid Gibson } 23688e099d14SDavid Gibson 2369a3a16211SMarc-André Lureau ObjectProperty * 2370a3a16211SMarc-André Lureau object_class_property_add_tm(ObjectClass *klass, const char *name, 2371d2623129SMarkus Armbruster void (*get)(Object *, struct tm *, Error **)) 237216bf7f52SDaniel P. Berrange { 237316bf7f52SDaniel P. Berrange TMProperty *prop = g_malloc0(sizeof(*prop)); 237416bf7f52SDaniel P. Berrange 237516bf7f52SDaniel P. Berrange prop->get = get; 237616bf7f52SDaniel P. Berrange 2377d2623129SMarkus Armbruster return object_class_property_add(klass, name, "struct tm", 2378d2623129SMarkus Armbruster get ? property_get_tm : NULL, 2379d2623129SMarkus Armbruster NULL, NULL, prop); 238016bf7f52SDaniel P. Berrange } 238116bf7f52SDaniel P. Berrange 2382*90c69fb9SMarkus Armbruster static char *object_get_type(Object *obj, Error **errp) 23832f262e06SPaolo Bonzini { 23842f262e06SPaolo Bonzini return g_strdup(object_get_typename(obj)); 23852f262e06SPaolo Bonzini } 23862f262e06SPaolo Bonzini 2387d7bce999SEric Blake static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, 2388d7bce999SEric Blake void *opaque, Error **errp) 2389e732ea63SMichael S. Tsirkin { 2390e732ea63SMichael S. Tsirkin uint8_t value = *(uint8_t *)opaque; 239151e72bc1SEric Blake visit_type_uint8(v, name, &value, errp); 2392e732ea63SMichael S. Tsirkin } 2393e732ea63SMichael S. Tsirkin 2394836e1b38SFelipe Franciosi static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name, 2395836e1b38SFelipe Franciosi void *opaque, Error **errp) 2396836e1b38SFelipe Franciosi { 2397836e1b38SFelipe Franciosi uint8_t *field = opaque; 2398836e1b38SFelipe Franciosi uint8_t value; 2399836e1b38SFelipe Franciosi Error *local_err = NULL; 2400836e1b38SFelipe Franciosi 240162a35aaaSMarkus Armbruster if (!visit_type_uint8(v, name, &value, &local_err)) { 2402836e1b38SFelipe Franciosi error_propagate(errp, local_err); 2403836e1b38SFelipe Franciosi return; 2404836e1b38SFelipe Franciosi } 2405836e1b38SFelipe Franciosi 2406836e1b38SFelipe Franciosi *field = value; 2407836e1b38SFelipe Franciosi } 2408836e1b38SFelipe Franciosi 2409d7bce999SEric Blake static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, 2410d7bce999SEric Blake void *opaque, Error **errp) 2411e732ea63SMichael S. Tsirkin { 2412e732ea63SMichael S. Tsirkin uint16_t value = *(uint16_t *)opaque; 241351e72bc1SEric Blake visit_type_uint16(v, name, &value, errp); 2414e732ea63SMichael S. Tsirkin } 2415e732ea63SMichael S. Tsirkin 2416836e1b38SFelipe Franciosi static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name, 2417836e1b38SFelipe Franciosi void *opaque, Error **errp) 2418836e1b38SFelipe Franciosi { 2419836e1b38SFelipe Franciosi uint16_t *field = opaque; 2420836e1b38SFelipe Franciosi uint16_t value; 2421836e1b38SFelipe Franciosi Error *local_err = NULL; 2422836e1b38SFelipe Franciosi 242362a35aaaSMarkus Armbruster if (!visit_type_uint16(v, name, &value, &local_err)) { 2424836e1b38SFelipe Franciosi error_propagate(errp, local_err); 2425836e1b38SFelipe Franciosi return; 2426836e1b38SFelipe Franciosi } 2427836e1b38SFelipe Franciosi 2428836e1b38SFelipe Franciosi *field = value; 2429836e1b38SFelipe Franciosi } 2430836e1b38SFelipe Franciosi 2431d7bce999SEric Blake static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, 2432d7bce999SEric Blake void *opaque, Error **errp) 2433e732ea63SMichael S. Tsirkin { 2434e732ea63SMichael S. Tsirkin uint32_t value = *(uint32_t *)opaque; 243551e72bc1SEric Blake visit_type_uint32(v, name, &value, errp); 2436e732ea63SMichael S. Tsirkin } 2437e732ea63SMichael S. Tsirkin 2438836e1b38SFelipe Franciosi static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name, 2439836e1b38SFelipe Franciosi void *opaque, Error **errp) 2440836e1b38SFelipe Franciosi { 2441836e1b38SFelipe Franciosi uint32_t *field = opaque; 2442836e1b38SFelipe Franciosi uint32_t value; 2443836e1b38SFelipe Franciosi Error *local_err = NULL; 2444836e1b38SFelipe Franciosi 244562a35aaaSMarkus Armbruster if (!visit_type_uint32(v, name, &value, &local_err)) { 2446836e1b38SFelipe Franciosi error_propagate(errp, local_err); 2447836e1b38SFelipe Franciosi return; 2448836e1b38SFelipe Franciosi } 2449836e1b38SFelipe Franciosi 2450836e1b38SFelipe Franciosi *field = value; 2451836e1b38SFelipe Franciosi } 2452836e1b38SFelipe Franciosi 2453d7bce999SEric Blake static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, 2454d7bce999SEric Blake void *opaque, Error **errp) 2455e732ea63SMichael S. Tsirkin { 2456e732ea63SMichael S. Tsirkin uint64_t value = *(uint64_t *)opaque; 245751e72bc1SEric Blake visit_type_uint64(v, name, &value, errp); 2458e732ea63SMichael S. Tsirkin } 2459e732ea63SMichael S. Tsirkin 2460836e1b38SFelipe Franciosi static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name, 2461836e1b38SFelipe Franciosi void *opaque, Error **errp) 2462e732ea63SMichael S. Tsirkin { 2463836e1b38SFelipe Franciosi uint64_t *field = opaque; 2464836e1b38SFelipe Franciosi uint64_t value; 2465836e1b38SFelipe Franciosi Error *local_err = NULL; 2466836e1b38SFelipe Franciosi 246762a35aaaSMarkus Armbruster if (!visit_type_uint64(v, name, &value, &local_err)) { 2468836e1b38SFelipe Franciosi error_propagate(errp, local_err); 2469836e1b38SFelipe Franciosi return; 2470836e1b38SFelipe Franciosi } 2471836e1b38SFelipe Franciosi 2472836e1b38SFelipe Franciosi *field = value; 2473836e1b38SFelipe Franciosi } 2474836e1b38SFelipe Franciosi 247570251887SMarkus Armbruster ObjectProperty * 247670251887SMarkus Armbruster object_property_add_uint8_ptr(Object *obj, const char *name, 2477836e1b38SFelipe Franciosi const uint8_t *v, 2478d2623129SMarkus Armbruster ObjectPropertyFlags flags) 2479836e1b38SFelipe Franciosi { 2480836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2481836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2482836e1b38SFelipe Franciosi 2483836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2484836e1b38SFelipe Franciosi getter = property_get_uint8_ptr; 2485836e1b38SFelipe Franciosi } 2486836e1b38SFelipe Franciosi 2487836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2488836e1b38SFelipe Franciosi setter = property_set_uint8_ptr; 2489836e1b38SFelipe Franciosi } 2490836e1b38SFelipe Franciosi 249170251887SMarkus Armbruster return object_property_add(obj, name, "uint8", 2492d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 2493e732ea63SMichael S. Tsirkin } 2494e732ea63SMichael S. Tsirkin 2495a3a16211SMarc-André Lureau ObjectProperty * 2496a3a16211SMarc-André Lureau object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, 2497836e1b38SFelipe Franciosi const uint8_t *v, 2498d2623129SMarkus Armbruster ObjectPropertyFlags flags) 249916bf7f52SDaniel P. Berrange { 2500836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2501836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2502836e1b38SFelipe Franciosi 2503836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2504836e1b38SFelipe Franciosi getter = property_get_uint8_ptr; 2505836e1b38SFelipe Franciosi } 2506836e1b38SFelipe Franciosi 2507836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2508836e1b38SFelipe Franciosi setter = property_set_uint8_ptr; 2509836e1b38SFelipe Franciosi } 2510836e1b38SFelipe Franciosi 2511a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint8", 2512d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 251316bf7f52SDaniel P. Berrange } 251416bf7f52SDaniel P. Berrange 251570251887SMarkus Armbruster ObjectProperty * 251670251887SMarkus Armbruster object_property_add_uint16_ptr(Object *obj, const char *name, 2517836e1b38SFelipe Franciosi const uint16_t *v, 2518d2623129SMarkus Armbruster ObjectPropertyFlags flags) 2519e732ea63SMichael S. Tsirkin { 2520836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2521836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2522836e1b38SFelipe Franciosi 2523836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2524836e1b38SFelipe Franciosi getter = property_get_uint16_ptr; 2525836e1b38SFelipe Franciosi } 2526836e1b38SFelipe Franciosi 2527836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2528836e1b38SFelipe Franciosi setter = property_set_uint16_ptr; 2529836e1b38SFelipe Franciosi } 2530836e1b38SFelipe Franciosi 253170251887SMarkus Armbruster return object_property_add(obj, name, "uint16", 2532d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 2533e732ea63SMichael S. Tsirkin } 2534e732ea63SMichael S. Tsirkin 2535a3a16211SMarc-André Lureau ObjectProperty * 2536a3a16211SMarc-André Lureau object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, 2537836e1b38SFelipe Franciosi const uint16_t *v, 2538d2623129SMarkus Armbruster ObjectPropertyFlags flags) 253916bf7f52SDaniel P. Berrange { 2540836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2541836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2542836e1b38SFelipe Franciosi 2543836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2544836e1b38SFelipe Franciosi getter = property_get_uint16_ptr; 2545836e1b38SFelipe Franciosi } 2546836e1b38SFelipe Franciosi 2547836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2548836e1b38SFelipe Franciosi setter = property_set_uint16_ptr; 2549836e1b38SFelipe Franciosi } 2550836e1b38SFelipe Franciosi 2551a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint16", 2552d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 255316bf7f52SDaniel P. Berrange } 255416bf7f52SDaniel P. Berrange 255570251887SMarkus Armbruster ObjectProperty * 255670251887SMarkus Armbruster object_property_add_uint32_ptr(Object *obj, const char *name, 2557836e1b38SFelipe Franciosi const uint32_t *v, 2558d2623129SMarkus Armbruster ObjectPropertyFlags flags) 2559e732ea63SMichael S. Tsirkin { 2560836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2561836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2562836e1b38SFelipe Franciosi 2563836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2564836e1b38SFelipe Franciosi getter = property_get_uint32_ptr; 2565836e1b38SFelipe Franciosi } 2566836e1b38SFelipe Franciosi 2567836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2568836e1b38SFelipe Franciosi setter = property_set_uint32_ptr; 2569836e1b38SFelipe Franciosi } 2570836e1b38SFelipe Franciosi 257170251887SMarkus Armbruster return object_property_add(obj, name, "uint32", 2572d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 2573e732ea63SMichael S. Tsirkin } 2574e732ea63SMichael S. Tsirkin 2575a3a16211SMarc-André Lureau ObjectProperty * 2576a3a16211SMarc-André Lureau object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, 2577836e1b38SFelipe Franciosi const uint32_t *v, 2578d2623129SMarkus Armbruster ObjectPropertyFlags flags) 257916bf7f52SDaniel P. Berrange { 2580836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2581836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2582836e1b38SFelipe Franciosi 2583836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2584836e1b38SFelipe Franciosi getter = property_get_uint32_ptr; 2585836e1b38SFelipe Franciosi } 2586836e1b38SFelipe Franciosi 2587836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2588836e1b38SFelipe Franciosi setter = property_set_uint32_ptr; 2589836e1b38SFelipe Franciosi } 2590836e1b38SFelipe Franciosi 2591a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint32", 2592d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 259316bf7f52SDaniel P. Berrange } 259416bf7f52SDaniel P. Berrange 259570251887SMarkus Armbruster ObjectProperty * 259670251887SMarkus Armbruster object_property_add_uint64_ptr(Object *obj, const char *name, 2597836e1b38SFelipe Franciosi const uint64_t *v, 2598d2623129SMarkus Armbruster ObjectPropertyFlags flags) 2599e732ea63SMichael S. Tsirkin { 2600836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2601836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2602836e1b38SFelipe Franciosi 2603836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2604836e1b38SFelipe Franciosi getter = property_get_uint64_ptr; 2605836e1b38SFelipe Franciosi } 2606836e1b38SFelipe Franciosi 2607836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2608836e1b38SFelipe Franciosi setter = property_set_uint64_ptr; 2609836e1b38SFelipe Franciosi } 2610836e1b38SFelipe Franciosi 261170251887SMarkus Armbruster return object_property_add(obj, name, "uint64", 2612d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 2613e732ea63SMichael S. Tsirkin } 2614e732ea63SMichael S. Tsirkin 2615a3a16211SMarc-André Lureau ObjectProperty * 2616a3a16211SMarc-André Lureau object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, 2617836e1b38SFelipe Franciosi const uint64_t *v, 2618d2623129SMarkus Armbruster ObjectPropertyFlags flags) 261916bf7f52SDaniel P. Berrange { 2620836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL; 2621836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL; 2622836e1b38SFelipe Franciosi 2623836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) { 2624836e1b38SFelipe Franciosi getter = property_get_uint64_ptr; 2625836e1b38SFelipe Franciosi } 2626836e1b38SFelipe Franciosi 2627836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) { 2628836e1b38SFelipe Franciosi setter = property_set_uint64_ptr; 2629836e1b38SFelipe Franciosi } 2630836e1b38SFelipe Franciosi 2631a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint64", 2632d2623129SMarkus Armbruster getter, setter, NULL, (void *)v); 263316bf7f52SDaniel P. Berrange } 263416bf7f52SDaniel P. Berrange 2635ef7c7ff6SStefan Hajnoczi typedef struct { 2636ef7c7ff6SStefan Hajnoczi Object *target_obj; 26371590d266SEduardo Habkost char *target_name; 2638ef7c7ff6SStefan Hajnoczi } AliasProperty; 2639ef7c7ff6SStefan Hajnoczi 2640d7bce999SEric Blake static void property_get_alias(Object *obj, Visitor *v, const char *name, 2641d7bce999SEric Blake void *opaque, Error **errp) 2642ef7c7ff6SStefan Hajnoczi { 2643ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2644ef7c7ff6SStefan Hajnoczi 2645ef7c7ff6SStefan Hajnoczi object_property_get(prop->target_obj, v, prop->target_name, errp); 2646ef7c7ff6SStefan Hajnoczi } 2647ef7c7ff6SStefan Hajnoczi 2648d7bce999SEric Blake static void property_set_alias(Object *obj, Visitor *v, const char *name, 2649d7bce999SEric Blake void *opaque, Error **errp) 2650ef7c7ff6SStefan Hajnoczi { 2651ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2652ef7c7ff6SStefan Hajnoczi 2653ef7c7ff6SStefan Hajnoczi object_property_set(prop->target_obj, v, prop->target_name, errp); 2654ef7c7ff6SStefan Hajnoczi } 2655ef7c7ff6SStefan Hajnoczi 265664607d08SPaolo Bonzini static Object *property_resolve_alias(Object *obj, void *opaque, 2657ddfb0baaSMarkus Armbruster const char *part) 265864607d08SPaolo Bonzini { 265964607d08SPaolo Bonzini AliasProperty *prop = opaque; 266064607d08SPaolo Bonzini 266164607d08SPaolo Bonzini return object_resolve_path_component(prop->target_obj, prop->target_name); 266264607d08SPaolo Bonzini } 266364607d08SPaolo Bonzini 2664ef7c7ff6SStefan Hajnoczi static void property_release_alias(Object *obj, const char *name, void *opaque) 2665ef7c7ff6SStefan Hajnoczi { 2666ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque; 2667ef7c7ff6SStefan Hajnoczi 26681590d266SEduardo Habkost g_free(prop->target_name); 2669ef7c7ff6SStefan Hajnoczi g_free(prop); 2670ef7c7ff6SStefan Hajnoczi } 2671ef7c7ff6SStefan Hajnoczi 267270251887SMarkus Armbruster ObjectProperty * 267370251887SMarkus Armbruster object_property_add_alias(Object *obj, const char *name, 2674d2623129SMarkus Armbruster Object *target_obj, const char *target_name) 2675ef7c7ff6SStefan Hajnoczi { 2676ef7c7ff6SStefan Hajnoczi AliasProperty *prop; 267764607d08SPaolo Bonzini ObjectProperty *op; 2678ef7c7ff6SStefan Hajnoczi ObjectProperty *target_prop; 267970251887SMarkus Armbruster g_autofree char *prop_type = NULL; 2680ef7c7ff6SStefan Hajnoczi 2681d2623129SMarkus Armbruster target_prop = object_property_find(target_obj, target_name, 2682d2623129SMarkus Armbruster &error_abort); 2683ef7c7ff6SStefan Hajnoczi 2684d190698eSPaolo Bonzini if (object_property_is_child(target_prop)) { 2685d190698eSPaolo Bonzini prop_type = g_strdup_printf("link%s", 2686d190698eSPaolo Bonzini target_prop->type + strlen("child")); 2687d190698eSPaolo Bonzini } else { 2688d190698eSPaolo Bonzini prop_type = g_strdup(target_prop->type); 2689d190698eSPaolo Bonzini } 2690d190698eSPaolo Bonzini 2691ef7c7ff6SStefan Hajnoczi prop = g_malloc(sizeof(*prop)); 2692ef7c7ff6SStefan Hajnoczi prop->target_obj = target_obj; 26931590d266SEduardo Habkost prop->target_name = g_strdup(target_name); 2694ef7c7ff6SStefan Hajnoczi 2695d190698eSPaolo Bonzini op = object_property_add(obj, name, prop_type, 2696ef7c7ff6SStefan Hajnoczi property_get_alias, 2697ef7c7ff6SStefan Hajnoczi property_set_alias, 2698ef7c7ff6SStefan Hajnoczi property_release_alias, 2699d2623129SMarkus Armbruster prop); 270064607d08SPaolo Bonzini op->resolve = property_resolve_alias; 27010e76ed0aSMarc-André Lureau if (target_prop->defval) { 27020e76ed0aSMarc-André Lureau op->defval = qobject_ref(target_prop->defval); 27030e76ed0aSMarc-André Lureau } 2704d190698eSPaolo Bonzini 2705a18bb417SAndreas Färber object_property_set_description(obj, op->name, 27067eecec7dSMarkus Armbruster target_prop->description); 270770251887SMarkus Armbruster return op; 2708ef7c7ff6SStefan Hajnoczi } 2709ef7c7ff6SStefan Hajnoczi 271080742642SGonglei void object_property_set_description(Object *obj, const char *name, 27117eecec7dSMarkus Armbruster const char *description) 271280742642SGonglei { 271380742642SGonglei ObjectProperty *op; 271480742642SGonglei 27157eecec7dSMarkus Armbruster op = object_property_find(obj, name, &error_abort); 271680742642SGonglei g_free(op->description); 271780742642SGonglei op->description = g_strdup(description); 271880742642SGonglei } 271980742642SGonglei 272016bf7f52SDaniel P. Berrange void object_class_property_set_description(ObjectClass *klass, 272116bf7f52SDaniel P. Berrange const char *name, 27227eecec7dSMarkus Armbruster const char *description) 272316bf7f52SDaniel P. Berrange { 272416bf7f52SDaniel P. Berrange ObjectProperty *op; 272516bf7f52SDaniel P. Berrange 272616bf7f52SDaniel P. Berrange op = g_hash_table_lookup(klass->properties, name); 272716bf7f52SDaniel P. Berrange g_free(op->description); 272816bf7f52SDaniel P. Berrange op->description = g_strdup(description); 272916bf7f52SDaniel P. Berrange } 273016bf7f52SDaniel P. Berrange 27317439a036SMarc-André Lureau static void object_class_init(ObjectClass *klass, void *data) 27322f262e06SPaolo Bonzini { 2733*90c69fb9SMarkus Armbruster object_class_property_add_str(klass, "type", object_get_type, 2734d2623129SMarkus Armbruster NULL); 27352f262e06SPaolo Bonzini } 27362f262e06SPaolo Bonzini 2737745549c8SPaolo Bonzini static void register_types(void) 2738745549c8SPaolo Bonzini { 2739745549c8SPaolo Bonzini static TypeInfo interface_info = { 2740745549c8SPaolo Bonzini .name = TYPE_INTERFACE, 274133e95c63SAnthony Liguori .class_size = sizeof(InterfaceClass), 2742745549c8SPaolo Bonzini .abstract = true, 2743745549c8SPaolo Bonzini }; 2744745549c8SPaolo Bonzini 2745745549c8SPaolo Bonzini static TypeInfo object_info = { 2746745549c8SPaolo Bonzini .name = TYPE_OBJECT, 2747745549c8SPaolo Bonzini .instance_size = sizeof(Object), 27487439a036SMarc-André Lureau .class_init = object_class_init, 2749745549c8SPaolo Bonzini .abstract = true, 2750745549c8SPaolo Bonzini }; 2751745549c8SPaolo Bonzini 2752049cb3cfSPaolo Bonzini type_interface = type_register_internal(&interface_info); 2753049cb3cfSPaolo Bonzini type_register_internal(&object_info); 2754745549c8SPaolo Bonzini } 2755745549c8SPaolo Bonzini 2756745549c8SPaolo Bonzini type_init(register_types) 2757