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"
195df022cfSPeter Maydell #include "qemu/memalign.h"
207b1b5d19SPaolo Bonzini #include "qapi/visitor.h"
21b2cd7deeSPaolo Bonzini #include "qapi/string-input-visitor.h"
22b2cd7deeSPaolo Bonzini #include "qapi/string-output-visitor.h"
230e76ed0aSMarc-André Lureau #include "qapi/qobject-input-visitor.h"
24cbc94d97SPaolo Bonzini #include "qapi/forward-visitor.h"
25eb815e24SMarkus Armbruster #include "qapi/qapi-builtin-visit.h"
260e76ed0aSMarc-André Lureau #include "qapi/qmp/qjson.h"
27fa131d94SPaolo Bonzini #include "trace.h"
282f28d2ffSAnthony Liguori
297b7b7d18SPaolo Bonzini /* TODO: replace QObject with a simpler visitor to avoid a dependency
307b7b7d18SPaolo Bonzini * of the QOM core on QObject? */
3114cccb61SPaolo Bonzini #include "qom/qom-qobject.h"
327b1b5d19SPaolo Bonzini #include "qapi/qmp/qbool.h"
33125062e7SKevin Wolf #include "qapi/qmp/qlist.h"
3415280c36SMarkus Armbruster #include "qapi/qmp/qnum.h"
357b1b5d19SPaolo Bonzini #include "qapi/qmp/qstring.h"
36e02bdf1cSPhilippe Mathieu-Daudé #include "qemu/error-report.h"
377b7b7d18SPaolo Bonzini
382f28d2ffSAnthony Liguori #define MAX_INTERFACES 32
392f28d2ffSAnthony Liguori
402f28d2ffSAnthony Liguori typedef struct InterfaceImpl InterfaceImpl;
412f28d2ffSAnthony Liguori typedef struct TypeImpl TypeImpl;
422f28d2ffSAnthony Liguori
432f28d2ffSAnthony Liguori struct InterfaceImpl
442f28d2ffSAnthony Liguori {
4533e95c63SAnthony Liguori const char *typename;
462f28d2ffSAnthony Liguori };
472f28d2ffSAnthony Liguori
482f28d2ffSAnthony Liguori struct TypeImpl
492f28d2ffSAnthony Liguori {
502f28d2ffSAnthony Liguori const char *name;
512f28d2ffSAnthony Liguori
522f28d2ffSAnthony Liguori size_t class_size;
532f28d2ffSAnthony Liguori
542f28d2ffSAnthony Liguori size_t instance_size;
554c880f36SRichard Henderson size_t instance_align;
562f28d2ffSAnthony Liguori
572f28d2ffSAnthony Liguori void (*class_init)(ObjectClass *klass, void *data);
583b50e311SPaolo Bonzini void (*class_base_init)(ObjectClass *klass, void *data);
592f28d2ffSAnthony Liguori
602f28d2ffSAnthony Liguori void *class_data;
612f28d2ffSAnthony Liguori
622f28d2ffSAnthony Liguori void (*instance_init)(Object *obj);
638231c2ddSEduardo Habkost void (*instance_post_init)(Object *obj);
642f28d2ffSAnthony Liguori void (*instance_finalize)(Object *obj);
652f28d2ffSAnthony Liguori
662f28d2ffSAnthony Liguori bool abstract;
672f28d2ffSAnthony Liguori
682f28d2ffSAnthony Liguori const char *parent;
692f28d2ffSAnthony Liguori TypeImpl *parent_type;
702f28d2ffSAnthony Liguori
712f28d2ffSAnthony Liguori ObjectClass *class;
722f28d2ffSAnthony Liguori
732f28d2ffSAnthony Liguori int num_interfaces;
742f28d2ffSAnthony Liguori InterfaceImpl interfaces[MAX_INTERFACES];
752f28d2ffSAnthony Liguori };
762f28d2ffSAnthony Liguori
779970bd88SPaolo Bonzini static Type type_interface;
789970bd88SPaolo Bonzini
type_table_get(void)792f28d2ffSAnthony Liguori static GHashTable *type_table_get(void)
802f28d2ffSAnthony Liguori {
812f28d2ffSAnthony Liguori static GHashTable *type_table;
822f28d2ffSAnthony Liguori
832f28d2ffSAnthony Liguori if (type_table == NULL) {
842f28d2ffSAnthony Liguori type_table = g_hash_table_new(g_str_hash, g_str_equal);
852f28d2ffSAnthony Liguori }
862f28d2ffSAnthony Liguori
872f28d2ffSAnthony Liguori return type_table;
882f28d2ffSAnthony Liguori }
892f28d2ffSAnthony Liguori
90f54c19caSHervé Poussineau static bool enumerating_types;
91f54c19caSHervé Poussineau
type_table_add(TypeImpl * ti)922f28d2ffSAnthony Liguori static void type_table_add(TypeImpl *ti)
932f28d2ffSAnthony Liguori {
94f54c19caSHervé Poussineau assert(!enumerating_types);
952f28d2ffSAnthony Liguori g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
962f28d2ffSAnthony Liguori }
972f28d2ffSAnthony Liguori
type_table_lookup(const char * name)982f28d2ffSAnthony Liguori static TypeImpl *type_table_lookup(const char *name)
992f28d2ffSAnthony Liguori {
1002f28d2ffSAnthony Liguori return g_hash_table_lookup(type_table_get(), name);
1012f28d2ffSAnthony Liguori }
1022f28d2ffSAnthony Liguori
type_new(const TypeInfo * info)103b061dc41SPaolo Bonzini static TypeImpl *type_new(const TypeInfo *info)
1042f28d2ffSAnthony Liguori {
1052f28d2ffSAnthony Liguori TypeImpl *ti = g_malloc0(sizeof(*ti));
10633e95c63SAnthony Liguori int i;
1072f28d2ffSAnthony Liguori
1082f28d2ffSAnthony Liguori g_assert(info->name != NULL);
1092f28d2ffSAnthony Liguori
11073093354SAnthony Liguori if (type_table_lookup(info->name) != NULL) {
11173093354SAnthony Liguori fprintf(stderr, "Registering `%s' which already exists\n", info->name);
11273093354SAnthony Liguori abort();
11373093354SAnthony Liguori }
11473093354SAnthony Liguori
1152f28d2ffSAnthony Liguori ti->name = g_strdup(info->name);
1162f28d2ffSAnthony Liguori ti->parent = g_strdup(info->parent);
1172f28d2ffSAnthony Liguori
1182f28d2ffSAnthony Liguori ti->class_size = info->class_size;
1192f28d2ffSAnthony Liguori ti->instance_size = info->instance_size;
1204c880f36SRichard Henderson ti->instance_align = info->instance_align;
1212f28d2ffSAnthony Liguori
1222f28d2ffSAnthony Liguori ti->class_init = info->class_init;
1233b50e311SPaolo Bonzini ti->class_base_init = info->class_base_init;
1242f28d2ffSAnthony Liguori ti->class_data = info->class_data;
1252f28d2ffSAnthony Liguori
1262f28d2ffSAnthony Liguori ti->instance_init = info->instance_init;
1278231c2ddSEduardo Habkost ti->instance_post_init = info->instance_post_init;
1282f28d2ffSAnthony Liguori ti->instance_finalize = info->instance_finalize;
1292f28d2ffSAnthony Liguori
1302f28d2ffSAnthony Liguori ti->abstract = info->abstract;
1312f28d2ffSAnthony Liguori
13233e95c63SAnthony Liguori for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
13333e95c63SAnthony Liguori ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
1342f28d2ffSAnthony Liguori }
13533e95c63SAnthony Liguori ti->num_interfaces = i;
1362f28d2ffSAnthony Liguori
137b061dc41SPaolo Bonzini return ti;
138b061dc41SPaolo Bonzini }
1392f28d2ffSAnthony Liguori
type_name_is_valid(const char * name)140b447378eSThomas Huth static bool type_name_is_valid(const char *name)
141b447378eSThomas Huth {
142b447378eSThomas Huth const int slen = strlen(name);
143b447378eSThomas Huth int plen;
144b447378eSThomas Huth
145b447378eSThomas Huth g_assert(slen > 1);
146b447378eSThomas Huth
147b447378eSThomas Huth /*
148b447378eSThomas Huth * Ideally, the name should start with a letter - however, we've got
149b447378eSThomas Huth * too many names starting with a digit already, so allow digits here,
150b447378eSThomas Huth * too (except '0' which is not used yet)
151b447378eSThomas Huth */
152b447378eSThomas Huth if (!g_ascii_isalnum(name[0]) || name[0] == '0') {
153b447378eSThomas Huth return false;
154b447378eSThomas Huth }
155b447378eSThomas Huth
156b447378eSThomas Huth plen = strspn(name, "abcdefghijklmnopqrstuvwxyz"
157b447378eSThomas Huth "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
158b447378eSThomas Huth "0123456789-_.");
159b447378eSThomas Huth
160b447378eSThomas Huth return plen == slen;
161b447378eSThomas Huth }
162b447378eSThomas Huth
type_register_internal(const TypeInfo * info)163b061dc41SPaolo Bonzini static TypeImpl *type_register_internal(const TypeInfo *info)
164b061dc41SPaolo Bonzini {
165b061dc41SPaolo Bonzini TypeImpl *ti;
166b447378eSThomas Huth
167b447378eSThomas Huth if (!type_name_is_valid(info->name)) {
168b447378eSThomas Huth fprintf(stderr, "Registering '%s' with illegal type name\n", info->name);
169b447378eSThomas Huth abort();
170b447378eSThomas Huth }
171b447378eSThomas Huth
172b061dc41SPaolo Bonzini ti = type_new(info);
173b061dc41SPaolo Bonzini
174b061dc41SPaolo Bonzini type_table_add(ti);
1752f28d2ffSAnthony Liguori return ti;
1762f28d2ffSAnthony Liguori }
1772f28d2ffSAnthony Liguori
type_register(const TypeInfo * info)178049cb3cfSPaolo Bonzini TypeImpl *type_register(const TypeInfo *info)
179049cb3cfSPaolo Bonzini {
180049cb3cfSPaolo Bonzini assert(info->parent);
181049cb3cfSPaolo Bonzini return type_register_internal(info);
182049cb3cfSPaolo Bonzini }
183049cb3cfSPaolo Bonzini
type_register_static(const TypeInfo * info)1842f28d2ffSAnthony Liguori TypeImpl *type_register_static(const TypeInfo *info)
1852f28d2ffSAnthony Liguori {
1862f28d2ffSAnthony Liguori return type_register(info);
1872f28d2ffSAnthony Liguori }
1882f28d2ffSAnthony Liguori
type_register_static_array(const TypeInfo * infos,int nr_infos)189aa04c9d2SIgor Mammedov void type_register_static_array(const TypeInfo *infos, int nr_infos)
190aa04c9d2SIgor Mammedov {
191aa04c9d2SIgor Mammedov int i;
192aa04c9d2SIgor Mammedov
193aa04c9d2SIgor Mammedov for (i = 0; i < nr_infos; i++) {
194aa04c9d2SIgor Mammedov type_register_static(&infos[i]);
195aa04c9d2SIgor Mammedov }
196aa04c9d2SIgor Mammedov }
197aa04c9d2SIgor Mammedov
type_get_by_name_noload(const char * name)198144d80f6SPaolo Bonzini static TypeImpl *type_get_by_name_noload(const char *name)
1992f28d2ffSAnthony Liguori {
2002f28d2ffSAnthony Liguori if (name == NULL) {
2012f28d2ffSAnthony Liguori return NULL;
2022f28d2ffSAnthony Liguori }
2032f28d2ffSAnthony Liguori
2042f28d2ffSAnthony Liguori return type_table_lookup(name);
2052f28d2ffSAnthony Liguori }
2062f28d2ffSAnthony Liguori
type_get_or_load_by_name(const char * name,Error ** errp)207144d80f6SPaolo Bonzini static TypeImpl *type_get_or_load_by_name(const char *name, Error **errp)
208144d80f6SPaolo Bonzini {
209144d80f6SPaolo Bonzini TypeImpl *type = type_get_by_name_noload(name);
210144d80f6SPaolo Bonzini
211144d80f6SPaolo Bonzini #ifdef CONFIG_MODULES
212144d80f6SPaolo Bonzini if (!type) {
213144d80f6SPaolo Bonzini int rv = module_load_qom(name, errp);
214144d80f6SPaolo Bonzini if (rv > 0) {
215144d80f6SPaolo Bonzini type = type_get_by_name_noload(name);
216144d80f6SPaolo Bonzini } else {
217144d80f6SPaolo Bonzini error_prepend(errp, "could not load a module for type '%s'", name);
218144d80f6SPaolo Bonzini return NULL;
219144d80f6SPaolo Bonzini }
220144d80f6SPaolo Bonzini }
221144d80f6SPaolo Bonzini #endif
222144d80f6SPaolo Bonzini if (!type) {
223144d80f6SPaolo Bonzini error_setg(errp, "unknown type '%s'", name);
224144d80f6SPaolo Bonzini }
225144d80f6SPaolo Bonzini
226144d80f6SPaolo Bonzini return type;
227144d80f6SPaolo Bonzini }
228144d80f6SPaolo Bonzini
type_get_parent(TypeImpl * type)2292f28d2ffSAnthony Liguori static TypeImpl *type_get_parent(TypeImpl *type)
2302f28d2ffSAnthony Liguori {
2312f28d2ffSAnthony Liguori if (!type->parent_type && type->parent) {
232144d80f6SPaolo Bonzini type->parent_type = type_get_by_name_noload(type->parent);
23389d337fdSPhilippe Mathieu-Daudé if (!type->parent_type) {
23489d337fdSPhilippe Mathieu-Daudé fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
23589d337fdSPhilippe Mathieu-Daudé type->name, type->parent);
23689d337fdSPhilippe Mathieu-Daudé abort();
23789d337fdSPhilippe Mathieu-Daudé }
2382f28d2ffSAnthony Liguori }
2392f28d2ffSAnthony Liguori
2402f28d2ffSAnthony Liguori return type->parent_type;
2412f28d2ffSAnthony Liguori }
2422f28d2ffSAnthony Liguori
type_has_parent(TypeImpl * type)2432f28d2ffSAnthony Liguori static bool type_has_parent(TypeImpl *type)
2442f28d2ffSAnthony Liguori {
2452f28d2ffSAnthony Liguori return (type->parent != NULL);
2462f28d2ffSAnthony Liguori }
2472f28d2ffSAnthony Liguori
type_class_get_size(TypeImpl * ti)2482f28d2ffSAnthony Liguori static size_t type_class_get_size(TypeImpl *ti)
2492f28d2ffSAnthony Liguori {
2502f28d2ffSAnthony Liguori if (ti->class_size) {
2512f28d2ffSAnthony Liguori return ti->class_size;
2522f28d2ffSAnthony Liguori }
2532f28d2ffSAnthony Liguori
2542f28d2ffSAnthony Liguori if (type_has_parent(ti)) {
2552f28d2ffSAnthony Liguori return type_class_get_size(type_get_parent(ti));
2562f28d2ffSAnthony Liguori }
2572f28d2ffSAnthony Liguori
2582f28d2ffSAnthony Liguori return sizeof(ObjectClass);
2592f28d2ffSAnthony Liguori }
2602f28d2ffSAnthony Liguori
type_object_get_size(TypeImpl * ti)261aca59af6SIgor Mitsyanko static size_t type_object_get_size(TypeImpl *ti)
262aca59af6SIgor Mitsyanko {
263aca59af6SIgor Mitsyanko if (ti->instance_size) {
264aca59af6SIgor Mitsyanko return ti->instance_size;
265aca59af6SIgor Mitsyanko }
266aca59af6SIgor Mitsyanko
267aca59af6SIgor Mitsyanko if (type_has_parent(ti)) {
268aca59af6SIgor Mitsyanko return type_object_get_size(type_get_parent(ti));
269aca59af6SIgor Mitsyanko }
270aca59af6SIgor Mitsyanko
271aca59af6SIgor Mitsyanko return 0;
272aca59af6SIgor Mitsyanko }
273aca59af6SIgor Mitsyanko
type_object_get_align(TypeImpl * ti)274ad4ec279SRichard Henderson static size_t type_object_get_align(TypeImpl *ti)
275ad4ec279SRichard Henderson {
276ad4ec279SRichard Henderson if (ti->instance_align) {
277ad4ec279SRichard Henderson return ti->instance_align;
278ad4ec279SRichard Henderson }
279ad4ec279SRichard Henderson
280ad4ec279SRichard Henderson if (type_has_parent(ti)) {
281ad4ec279SRichard Henderson return type_object_get_align(type_get_parent(ti));
282ad4ec279SRichard Henderson }
283ad4ec279SRichard Henderson
284ad4ec279SRichard Henderson return 0;
285ad4ec279SRichard Henderson }
286ad4ec279SRichard Henderson
type_is_ancestor(TypeImpl * type,TypeImpl * target_type)28733e95c63SAnthony Liguori static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
2882f28d2ffSAnthony Liguori {
28933e95c63SAnthony Liguori assert(target_type);
2902f28d2ffSAnthony Liguori
291b30d8054SCao jin /* Check if target_type is a direct ancestor of type */
29233e95c63SAnthony Liguori while (type) {
29333e95c63SAnthony Liguori if (type == target_type) {
29433e95c63SAnthony Liguori return true;
29533e95c63SAnthony Liguori }
29633e95c63SAnthony Liguori
29733e95c63SAnthony Liguori type = type_get_parent(type);
29833e95c63SAnthony Liguori }
29933e95c63SAnthony Liguori
30033e95c63SAnthony Liguori return false;
30133e95c63SAnthony Liguori }
30233e95c63SAnthony Liguori
30333e95c63SAnthony Liguori static void type_initialize(TypeImpl *ti);
30433e95c63SAnthony Liguori
type_initialize_interface(TypeImpl * ti,TypeImpl * interface_type,TypeImpl * parent_type)305b061dc41SPaolo Bonzini static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
306b061dc41SPaolo Bonzini TypeImpl *parent_type)
30733e95c63SAnthony Liguori {
30833e95c63SAnthony Liguori InterfaceClass *new_iface;
30933e95c63SAnthony Liguori TypeInfo info = { };
31033e95c63SAnthony Liguori TypeImpl *iface_impl;
31133e95c63SAnthony Liguori
312b061dc41SPaolo Bonzini info.parent = parent_type->name;
313b061dc41SPaolo Bonzini info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
31433e95c63SAnthony Liguori info.abstract = true;
31533e95c63SAnthony Liguori
316b061dc41SPaolo Bonzini iface_impl = type_new(&info);
317b061dc41SPaolo Bonzini iface_impl->parent_type = parent_type;
31833e95c63SAnthony Liguori type_initialize(iface_impl);
31933e95c63SAnthony Liguori g_free((char *)info.name);
32033e95c63SAnthony Liguori
32133e95c63SAnthony Liguori new_iface = (InterfaceClass *)iface_impl->class;
32233e95c63SAnthony Liguori new_iface->concrete_class = ti->class;
323b061dc41SPaolo Bonzini new_iface->interface_type = interface_type;
32433e95c63SAnthony Liguori
3253d91293eSMasahiro Yamada ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface);
3262f28d2ffSAnthony Liguori }
3272f28d2ffSAnthony Liguori
object_property_free(gpointer data)32816bf7f52SDaniel P. Berrange static void object_property_free(gpointer data)
32916bf7f52SDaniel P. Berrange {
33016bf7f52SDaniel P. Berrange ObjectProperty *prop = data;
33116bf7f52SDaniel P. Berrange
3320e76ed0aSMarc-André Lureau if (prop->defval) {
3330e76ed0aSMarc-André Lureau qobject_unref(prop->defval);
3340e76ed0aSMarc-André Lureau prop->defval = NULL;
3350e76ed0aSMarc-André Lureau }
33616bf7f52SDaniel P. Berrange g_free(prop->name);
33716bf7f52SDaniel P. Berrange g_free(prop->type);
33816bf7f52SDaniel P. Berrange g_free(prop->description);
33916bf7f52SDaniel P. Berrange g_free(prop);
34016bf7f52SDaniel P. Berrange }
34116bf7f52SDaniel P. Berrange
type_initialize(TypeImpl * ti)342ac451033SIgor Mitsyanko static void type_initialize(TypeImpl *ti)
3432f28d2ffSAnthony Liguori {
344745549c8SPaolo Bonzini TypeImpl *parent;
3452f28d2ffSAnthony Liguori
3462f28d2ffSAnthony Liguori if (ti->class) {
3472f28d2ffSAnthony Liguori return;
3482f28d2ffSAnthony Liguori }
3492f28d2ffSAnthony Liguori
3502f28d2ffSAnthony Liguori ti->class_size = type_class_get_size(ti);
351aca59af6SIgor Mitsyanko ti->instance_size = type_object_get_size(ti);
352ad4ec279SRichard Henderson ti->instance_align = type_object_get_align(ti);
3531c6d75d5SEduardo Habkost /* Any type with zero instance_size is implicitly abstract.
3541c6d75d5SEduardo Habkost * This means interface types are all abstract.
3551c6d75d5SEduardo Habkost */
3561c6d75d5SEduardo Habkost if (ti->instance_size == 0) {
3571c6d75d5SEduardo Habkost ti->abstract = true;
3581c6d75d5SEduardo Habkost }
359422ca143SMarc-André Lureau if (type_is_ancestor(ti, type_interface)) {
360422ca143SMarc-André Lureau assert(ti->instance_size == 0);
361422ca143SMarc-André Lureau assert(ti->abstract);
362422ca143SMarc-André Lureau assert(!ti->instance_init);
363422ca143SMarc-André Lureau assert(!ti->instance_post_init);
364422ca143SMarc-André Lureau assert(!ti->instance_finalize);
365422ca143SMarc-André Lureau assert(!ti->num_interfaces);
366422ca143SMarc-André Lureau }
3672f28d2ffSAnthony Liguori ti->class = g_malloc0(ti->class_size);
3682f28d2ffSAnthony Liguori
369745549c8SPaolo Bonzini parent = type_get_parent(ti);
370745549c8SPaolo Bonzini if (parent) {
371ac451033SIgor Mitsyanko type_initialize(parent);
37233e95c63SAnthony Liguori GSList *e;
37333e95c63SAnthony Liguori int i;
3742f28d2ffSAnthony Liguori
375719a3077SMarkus Armbruster g_assert(parent->class_size <= ti->class_size);
376d5e633fcSMarc-André Lureau g_assert(parent->instance_size <= ti->instance_size);
377745549c8SPaolo Bonzini memcpy(ti->class, parent->class, parent->class_size);
3783e407de4SPeter Crosthwaite ti->class->interfaces = NULL;
37933e95c63SAnthony Liguori
38033e95c63SAnthony Liguori for (e = parent->class->interfaces; e; e = e->next) {
381b061dc41SPaolo Bonzini InterfaceClass *iface = e->data;
382b061dc41SPaolo Bonzini ObjectClass *klass = OBJECT_CLASS(iface);
383b061dc41SPaolo Bonzini
384b061dc41SPaolo Bonzini type_initialize_interface(ti, iface->interface_type, klass->type);
38533e95c63SAnthony Liguori }
38633e95c63SAnthony Liguori
38733e95c63SAnthony Liguori for (i = 0; i < ti->num_interfaces; i++) {
388144d80f6SPaolo Bonzini TypeImpl *t = type_get_by_name_noload(ti->interfaces[i].typename);
389a9ee3a9eSPhilippe Mathieu-Daudé if (!t) {
390a9ee3a9eSPhilippe Mathieu-Daudé error_report("missing interface '%s' for object '%s'",
391a9ee3a9eSPhilippe Mathieu-Daudé ti->interfaces[i].typename, parent->name);
392a9ee3a9eSPhilippe Mathieu-Daudé abort();
393a9ee3a9eSPhilippe Mathieu-Daudé }
39433e95c63SAnthony Liguori for (e = ti->class->interfaces; e; e = e->next) {
39533e95c63SAnthony Liguori TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
39633e95c63SAnthony Liguori
39733e95c63SAnthony Liguori if (type_is_ancestor(target_type, t)) {
39833e95c63SAnthony Liguori break;
39933e95c63SAnthony Liguori }
40033e95c63SAnthony Liguori }
40133e95c63SAnthony Liguori
40233e95c63SAnthony Liguori if (e) {
40333e95c63SAnthony Liguori continue;
40433e95c63SAnthony Liguori }
40533e95c63SAnthony Liguori
406b061dc41SPaolo Bonzini type_initialize_interface(ti, t, t);
40733e95c63SAnthony Liguori }
408745549c8SPaolo Bonzini }
4092f28d2ffSAnthony Liguori
410e5a0cc5eSMasahiro Yamada ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
411e5a0cc5eSMasahiro Yamada object_property_free);
412e5a0cc5eSMasahiro Yamada
413745549c8SPaolo Bonzini ti->class->type = ti;
4143b50e311SPaolo Bonzini
4153b50e311SPaolo Bonzini while (parent) {
4163b50e311SPaolo Bonzini if (parent->class_base_init) {
4173b50e311SPaolo Bonzini parent->class_base_init(ti->class, ti->class_data);
4183b50e311SPaolo Bonzini }
4193b50e311SPaolo Bonzini parent = type_get_parent(parent);
4203b50e311SPaolo Bonzini }
4212f28d2ffSAnthony Liguori
4222f28d2ffSAnthony Liguori if (ti->class_init) {
4232f28d2ffSAnthony Liguori ti->class_init(ti->class, ti->class_data);
4242f28d2ffSAnthony Liguori }
4252f28d2ffSAnthony Liguori }
4262f28d2ffSAnthony Liguori
object_init_with_type(Object * obj,TypeImpl * ti)4272f28d2ffSAnthony Liguori static void object_init_with_type(Object *obj, TypeImpl *ti)
4282f28d2ffSAnthony Liguori {
4292f28d2ffSAnthony Liguori if (type_has_parent(ti)) {
4302f28d2ffSAnthony Liguori object_init_with_type(obj, type_get_parent(ti));
4312f28d2ffSAnthony Liguori }
4322f28d2ffSAnthony Liguori
4332f28d2ffSAnthony Liguori if (ti->instance_init) {
4342f28d2ffSAnthony Liguori ti->instance_init(obj);
4352f28d2ffSAnthony Liguori }
4362f28d2ffSAnthony Liguori }
4372f28d2ffSAnthony Liguori
object_post_init_with_type(Object * obj,TypeImpl * ti)4388231c2ddSEduardo Habkost static void object_post_init_with_type(Object *obj, TypeImpl *ti)
4398231c2ddSEduardo Habkost {
4408231c2ddSEduardo Habkost if (ti->instance_post_init) {
4418231c2ddSEduardo Habkost ti->instance_post_init(obj);
4428231c2ddSEduardo Habkost }
4438231c2ddSEduardo Habkost
4448231c2ddSEduardo Habkost if (type_has_parent(ti)) {
4458231c2ddSEduardo Habkost object_post_init_with_type(obj, type_get_parent(ti));
4468231c2ddSEduardo Habkost }
4478231c2ddSEduardo Habkost }
4488231c2ddSEduardo Habkost
object_apply_global_props(Object * obj,const GPtrArray * props,Error ** errp)4496fd5bef1SMarkus Armbruster bool object_apply_global_props(Object *obj, const GPtrArray *props,
4506fd5bef1SMarkus Armbruster Error **errp)
451ea9ce893SMarc-André Lureau {
452ea9ce893SMarc-André Lureau int i;
453ea9ce893SMarc-André Lureau
454ea9ce893SMarc-André Lureau if (!props) {
4556fd5bef1SMarkus Armbruster return true;
456ea9ce893SMarc-André Lureau }
457ea9ce893SMarc-André Lureau
458ea9ce893SMarc-André Lureau for (i = 0; i < props->len; i++) {
459ea9ce893SMarc-André Lureau GlobalProperty *p = g_ptr_array_index(props, i);
460d769f0dfSEduardo Habkost Error *err = NULL;
461ea9ce893SMarc-André Lureau
462ea9ce893SMarc-André Lureau if (object_dynamic_cast(obj, p->driver) == NULL) {
463ea9ce893SMarc-André Lureau continue;
464ea9ce893SMarc-André Lureau }
465efba1595SDaniel P. Berrangé if (p->optional && !object_property_find(obj, p->property)) {
46692fd453cSDr. David Alan Gilbert continue;
46792fd453cSDr. David Alan Gilbert }
468ea9ce893SMarc-André Lureau p->used = true;
469778a2dc5SMarkus Armbruster if (!object_property_parse(obj, p->property, p->value, &err)) {
470ea9ce893SMarc-André Lureau error_prepend(&err, "can't apply global %s.%s=%s: ",
471ea9ce893SMarc-André Lureau p->driver, p->property, p->value);
47250545b2cSMarc-André Lureau /*
47350545b2cSMarc-André Lureau * If errp != NULL, propagate error and return.
47450545b2cSMarc-André Lureau * If errp == NULL, report a warning, but keep going
47550545b2cSMarc-André Lureau * with the remaining globals.
47650545b2cSMarc-André Lureau */
47750545b2cSMarc-André Lureau if (errp) {
478ea9ce893SMarc-André Lureau error_propagate(errp, err);
4796fd5bef1SMarkus Armbruster return false;
48050545b2cSMarc-André Lureau } else {
48150545b2cSMarc-André Lureau warn_report_err(err);
48250545b2cSMarc-André Lureau }
483ea9ce893SMarc-André Lureau }
484ea9ce893SMarc-André Lureau }
4856fd5bef1SMarkus Armbruster
4866fd5bef1SMarkus Armbruster return true;
487ea9ce893SMarc-André Lureau }
488ea9ce893SMarc-André Lureau
489617902afSMarkus Armbruster /*
490617902afSMarkus Armbruster * Global property defaults
491617902afSMarkus Armbruster * Slot 0: accelerator's global property defaults
492617902afSMarkus Armbruster * Slot 1: machine's global property defaults
4931fff3c20SPaolo Bonzini * Slot 2: global properties from legacy command line option
494617902afSMarkus Armbruster * Each is a GPtrArray of of GlobalProperty.
495617902afSMarkus Armbruster * Applied in order, later entries override earlier ones.
496617902afSMarkus Armbruster */
4971fff3c20SPaolo Bonzini static GPtrArray *object_compat_props[3];
4981fff3c20SPaolo Bonzini
4991fff3c20SPaolo Bonzini /*
5001fff3c20SPaolo Bonzini * Retrieve @GPtrArray for global property defined with options
5011fff3c20SPaolo Bonzini * other than "-global". These are generally used for syntactic
5021fff3c20SPaolo Bonzini * sugar and legacy command line options.
5031fff3c20SPaolo Bonzini */
object_register_sugar_prop(const char * driver,const char * prop,const char * value,bool optional)504a8dc82ceSGreg Kurz void object_register_sugar_prop(const char *driver, const char *prop,
505a8dc82ceSGreg Kurz const char *value, bool optional)
5061fff3c20SPaolo Bonzini {
5071fff3c20SPaolo Bonzini GlobalProperty *g;
5081fff3c20SPaolo Bonzini if (!object_compat_props[2]) {
5091fff3c20SPaolo Bonzini object_compat_props[2] = g_ptr_array_new();
5101fff3c20SPaolo Bonzini }
5111fff3c20SPaolo Bonzini g = g_new0(GlobalProperty, 1);
5121fff3c20SPaolo Bonzini g->driver = g_strdup(driver);
5131fff3c20SPaolo Bonzini g->property = g_strdup(prop);
5141fff3c20SPaolo Bonzini g->value = g_strdup(value);
515a8dc82ceSGreg Kurz g->optional = optional;
5161fff3c20SPaolo Bonzini g_ptr_array_add(object_compat_props[2], g);
5171fff3c20SPaolo Bonzini }
518617902afSMarkus Armbruster
519617902afSMarkus Armbruster /*
520617902afSMarkus Armbruster * Set machine's global property defaults to @compat_props.
521617902afSMarkus Armbruster * May be called at most once.
522617902afSMarkus Armbruster */
object_set_machine_compat_props(GPtrArray * compat_props)523617902afSMarkus Armbruster void object_set_machine_compat_props(GPtrArray *compat_props)
524617902afSMarkus Armbruster {
525617902afSMarkus Armbruster assert(!object_compat_props[1]);
526617902afSMarkus Armbruster object_compat_props[1] = compat_props;
527617902afSMarkus Armbruster }
528617902afSMarkus Armbruster
529617902afSMarkus Armbruster /*
530617902afSMarkus Armbruster * Set accelerator's global property defaults to @compat_props.
531617902afSMarkus Armbruster * May be called at most once.
532617902afSMarkus Armbruster */
object_set_accelerator_compat_props(GPtrArray * compat_props)533617902afSMarkus Armbruster void object_set_accelerator_compat_props(GPtrArray *compat_props)
534617902afSMarkus Armbruster {
535617902afSMarkus Armbruster assert(!object_compat_props[0]);
536617902afSMarkus Armbruster object_compat_props[0] = compat_props;
537617902afSMarkus Armbruster }
538617902afSMarkus Armbruster
object_apply_compat_props(Object * obj)539617902afSMarkus Armbruster void object_apply_compat_props(Object *obj)
540617902afSMarkus Armbruster {
541617902afSMarkus Armbruster int i;
542617902afSMarkus Armbruster
543617902afSMarkus Armbruster for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
544617902afSMarkus Armbruster object_apply_global_props(obj, object_compat_props[i],
5451fff3c20SPaolo Bonzini i == 2 ? &error_fatal : &error_abort);
546617902afSMarkus Armbruster }
547617902afSMarkus Armbruster }
548617902afSMarkus Armbruster
object_class_property_init_all(Object * obj)5492a1be4b3SMarc-André Lureau static void object_class_property_init_all(Object *obj)
5502a1be4b3SMarc-André Lureau {
5512a1be4b3SMarc-André Lureau ObjectPropertyIterator iter;
5522a1be4b3SMarc-André Lureau ObjectProperty *prop;
5532a1be4b3SMarc-André Lureau
5542a1be4b3SMarc-André Lureau object_class_property_iter_init(&iter, object_get_class(obj));
5552a1be4b3SMarc-André Lureau while ((prop = object_property_iter_next(&iter))) {
5562a1be4b3SMarc-André Lureau if (prop->init) {
5572a1be4b3SMarc-André Lureau prop->init(obj, prop);
5582a1be4b3SMarc-André Lureau }
5592a1be4b3SMarc-André Lureau }
5602a1be4b3SMarc-André Lureau }
5612a1be4b3SMarc-André Lureau
object_initialize_with_type(Object * obj,size_t size,TypeImpl * type)562e27a9595SMasahiro Yamada static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
5632f28d2ffSAnthony Liguori {
564ac451033SIgor Mitsyanko type_initialize(type);
565aca59af6SIgor Mitsyanko
566719a3077SMarkus Armbruster g_assert(type->instance_size >= sizeof(Object));
5672f28d2ffSAnthony Liguori g_assert(type->abstract == false);
568719a3077SMarkus Armbruster g_assert(size >= type->instance_size);
5692f28d2ffSAnthony Liguori
5702f28d2ffSAnthony Liguori memset(obj, 0, type->instance_size);
5712f28d2ffSAnthony Liguori obj->class = type->class;
572764b6312SPaolo Bonzini object_ref(obj);
5732a1be4b3SMarc-André Lureau object_class_property_init_all(obj);
574b604a854SPavel Fedin obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
575b604a854SPavel Fedin NULL, object_property_free);
5762f28d2ffSAnthony Liguori object_init_with_type(obj, type);
5778231c2ddSEduardo Habkost object_post_init_with_type(obj, type);
5782f28d2ffSAnthony Liguori }
5792f28d2ffSAnthony Liguori
object_initialize(void * data,size_t size,const char * typename)580213f0c4fSAndreas Färber void object_initialize(void *data, size_t size, const char *typename)
5812f28d2ffSAnthony Liguori {
582144d80f6SPaolo Bonzini TypeImpl *type = type_get_or_load_by_name(typename, &error_fatal);
583e02bdf1cSPhilippe Mathieu-Daudé
5845b9237f6SAndreas Färber object_initialize_with_type(data, size, type);
5852f28d2ffSAnthony Liguori }
5862f28d2ffSAnthony Liguori
object_initialize_child_with_props(Object * parentobj,const char * propname,void * childobj,size_t size,const char * type,Error ** errp,...)5876fd5bef1SMarkus Armbruster bool object_initialize_child_with_props(Object *parentobj,
5889fc7fc4dSMarkus Armbruster const char *propname,
5896fd5bef1SMarkus Armbruster void *childobj, size_t size,
5906fd5bef1SMarkus Armbruster const char *type,
5910210b39dSThomas Huth Error **errp, ...)
5920210b39dSThomas Huth {
5930210b39dSThomas Huth va_list vargs;
5946fd5bef1SMarkus Armbruster bool ok;
5950210b39dSThomas Huth
5960210b39dSThomas Huth va_start(vargs, errp);
5976fd5bef1SMarkus Armbruster ok = object_initialize_child_with_propsv(parentobj, propname,
5986fd5bef1SMarkus Armbruster childobj, size, type, errp,
5996fd5bef1SMarkus Armbruster vargs);
6000210b39dSThomas Huth va_end(vargs);
6016fd5bef1SMarkus Armbruster return ok;
6020210b39dSThomas Huth }
6030210b39dSThomas Huth
object_initialize_child_with_propsv(Object * parentobj,const char * propname,void * childobj,size_t size,const char * type,Error ** errp,va_list vargs)6046fd5bef1SMarkus Armbruster bool object_initialize_child_with_propsv(Object *parentobj,
6059fc7fc4dSMarkus Armbruster const char *propname,
6066fd5bef1SMarkus Armbruster void *childobj, size_t size,
6076fd5bef1SMarkus Armbruster const char *type,
6080210b39dSThomas Huth Error **errp, va_list vargs)
6090210b39dSThomas Huth {
6106fd5bef1SMarkus Armbruster bool ok = false;
6110210b39dSThomas Huth Object *obj;
6123650b2deSMarc-André Lureau UserCreatable *uc;
6130210b39dSThomas Huth
6140210b39dSThomas Huth object_initialize(childobj, size, type);
6150210b39dSThomas Huth obj = OBJECT(childobj);
6160210b39dSThomas Huth
617b783f54dSMarkus Armbruster if (!object_set_propv(obj, errp, vargs)) {
6180210b39dSThomas Huth goto out;
6190210b39dSThomas Huth }
6200210b39dSThomas Huth
621d2623129SMarkus Armbruster object_property_add_child(parentobj, propname, obj);
6220210b39dSThomas Huth
6233650b2deSMarc-André Lureau uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
6243650b2deSMarc-André Lureau if (uc) {
625992861fbSMarkus Armbruster if (!user_creatable_complete(uc, errp)) {
6260210b39dSThomas Huth object_unparent(obj);
6270210b39dSThomas Huth goto out;
6280210b39dSThomas Huth }
6290210b39dSThomas Huth }
6300210b39dSThomas Huth
6316fd5bef1SMarkus Armbruster ok = true;
6326fd5bef1SMarkus Armbruster
633975ac455SMarkus Armbruster out:
6340210b39dSThomas Huth /*
635975ac455SMarkus Armbruster * We want @obj's reference to be 1 on success, 0 on failure.
636975ac455SMarkus Armbruster * On success, it's 2: one taken by object_initialize(), and one
637975ac455SMarkus Armbruster * by object_property_add_child().
638975ac455SMarkus Armbruster * On failure in object_initialize() or earlier, it's 1.
639975ac455SMarkus Armbruster * On failure afterwards, it's also 1: object_unparent() releases
640975ac455SMarkus Armbruster * the reference taken by object_property_add_child().
6410210b39dSThomas Huth */
6420210b39dSThomas Huth object_unref(obj);
6436fd5bef1SMarkus Armbruster return ok;
6440210b39dSThomas Huth }
6450210b39dSThomas Huth
object_initialize_child_internal(Object * parent,const char * propname,void * child,size_t size,const char * type)6469fc7fc4dSMarkus Armbruster void object_initialize_child_internal(Object *parent,
6479fc7fc4dSMarkus Armbruster const char *propname,
6489fc7fc4dSMarkus Armbruster void *child, size_t size,
6499fc7fc4dSMarkus Armbruster const char *type)
6509fc7fc4dSMarkus Armbruster {
6519fc7fc4dSMarkus Armbruster object_initialize_child_with_props(parent, propname, child, size, type,
6529fc7fc4dSMarkus Armbruster &error_abort, NULL);
6539fc7fc4dSMarkus Armbruster }
6549fc7fc4dSMarkus Armbruster
object_property_is_child(ObjectProperty * prop)6555d9d3f47SAndreas Färber static inline bool object_property_is_child(ObjectProperty *prop)
6565d9d3f47SAndreas Färber {
6575d9d3f47SAndreas Färber return strstart(prop->type, "child<", NULL);
6585d9d3f47SAndreas Färber }
6595d9d3f47SAndreas Färber
object_property_del_all(Object * obj)66057c9fafeSAnthony Liguori static void object_property_del_all(Object *obj)
66157c9fafeSAnthony Liguori {
6629859faccSMarc-André Lureau g_autoptr(GHashTable) done = g_hash_table_new(NULL, NULL);
663b604a854SPavel Fedin ObjectProperty *prop;
6649859faccSMarc-André Lureau ObjectPropertyIterator iter;
665b604a854SPavel Fedin bool released;
66657c9fafeSAnthony Liguori
667b604a854SPavel Fedin do {
668b604a854SPavel Fedin released = false;
6699859faccSMarc-André Lureau object_property_iter_init(&iter, obj);
6709859faccSMarc-André Lureau while ((prop = object_property_iter_next(&iter)) != NULL) {
6719859faccSMarc-André Lureau if (g_hash_table_add(done, prop)) {
67257c9fafeSAnthony Liguori if (prop->release) {
67357c9fafeSAnthony Liguori prop->release(obj, prop->name, prop->opaque);
674b604a854SPavel Fedin released = true;
675b604a854SPavel Fedin break;
67657c9fafeSAnthony Liguori }
6779859faccSMarc-André Lureau }
678b604a854SPavel Fedin }
679b604a854SPavel Fedin } while (released);
68057c9fafeSAnthony Liguori
681b604a854SPavel Fedin g_hash_table_unref(obj->properties);
68257c9fafeSAnthony Liguori }
68357c9fafeSAnthony Liguori
object_property_del_child(Object * obj,Object * child)684f73a32a5SMarkus Armbruster static void object_property_del_child(Object *obj, Object *child)
68557c9fafeSAnthony Liguori {
68657c9fafeSAnthony Liguori ObjectProperty *prop;
687b604a854SPavel Fedin GHashTableIter iter;
688b604a854SPavel Fedin gpointer key, value;
68957c9fafeSAnthony Liguori
690b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties);
691b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) {
692b604a854SPavel Fedin prop = value;
6935d9d3f47SAndreas Färber if (object_property_is_child(prop) && prop->opaque == child) {
694b604a854SPavel Fedin if (prop->release) {
695b604a854SPavel Fedin prop->release(obj, prop->name, prop->opaque);
696b604a854SPavel Fedin prop->release = NULL;
697b604a854SPavel Fedin }
698b604a854SPavel Fedin break;
699b604a854SPavel Fedin }
700b604a854SPavel Fedin }
701b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties);
702b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, &key, &value)) {
703b604a854SPavel Fedin prop = value;
704b604a854SPavel Fedin if (object_property_is_child(prop) && prop->opaque == child) {
705b604a854SPavel Fedin g_hash_table_iter_remove(&iter);
7066c1fdcf9SPaolo Bonzini break;
70757c9fafeSAnthony Liguori }
70857c9fafeSAnthony Liguori }
70957c9fafeSAnthony Liguori }
71057c9fafeSAnthony Liguori
object_unparent(Object * obj)71157c9fafeSAnthony Liguori void object_unparent(Object *obj)
71257c9fafeSAnthony Liguori {
713e998fa8dSMichael S. Tsirkin if (obj->parent) {
714f73a32a5SMarkus Armbruster object_property_del_child(obj->parent, obj);
715e998fa8dSMichael S. Tsirkin }
71657c9fafeSAnthony Liguori }
71757c9fafeSAnthony Liguori
object_deinit(Object * obj,TypeImpl * type)7182f28d2ffSAnthony Liguori static void object_deinit(Object *obj, TypeImpl *type)
7192f28d2ffSAnthony Liguori {
7202f28d2ffSAnthony Liguori if (type->instance_finalize) {
7212f28d2ffSAnthony Liguori type->instance_finalize(obj);
7222f28d2ffSAnthony Liguori }
7232f28d2ffSAnthony Liguori
7242f28d2ffSAnthony Liguori if (type_has_parent(type)) {
7252f28d2ffSAnthony Liguori object_deinit(obj, type_get_parent(type));
7262f28d2ffSAnthony Liguori }
7272f28d2ffSAnthony Liguori }
7282f28d2ffSAnthony Liguori
object_finalize(void * data)729339c2708SPaolo Bonzini static void object_finalize(void *data)
7302f28d2ffSAnthony Liguori {
7312f28d2ffSAnthony Liguori Object *obj = data;
7322f28d2ffSAnthony Liguori TypeImpl *ti = obj->class->type;
7332f28d2ffSAnthony Liguori
73457c9fafeSAnthony Liguori object_property_del_all(obj);
73576a6e1ccSPaolo Bonzini object_deinit(obj, ti);
736db85b575SAnthony Liguori
737719a3077SMarkus Armbruster g_assert(obj->ref == 0);
73863f957acSEduardo Habkost g_assert(obj->parent == NULL);
739fde9bf44SPaolo Bonzini if (obj->free) {
740fde9bf44SPaolo Bonzini obj->free(obj);
741fde9bf44SPaolo Bonzini }
7422f28d2ffSAnthony Liguori }
7432f28d2ffSAnthony Liguori
7444c880f36SRichard Henderson /* Find the minimum alignment guaranteed by the system malloc. */
7454c880f36SRichard Henderson #if __STDC_VERSION__ >= 201112L
7463a2e982dSDoug Evans typedef max_align_t qemu_max_align_t;
7474c880f36SRichard Henderson #else
7484c880f36SRichard Henderson typedef union {
7494c880f36SRichard Henderson long l;
7504c880f36SRichard Henderson void *p;
7514c880f36SRichard Henderson double d;
7524c880f36SRichard Henderson long double ld;
7534c880f36SRichard Henderson } qemu_max_align_t;
7544c880f36SRichard Henderson #endif
7554c880f36SRichard Henderson
object_new_with_type(Type type)75663f7b10bSMarc-André Lureau static Object *object_new_with_type(Type type)
7572f28d2ffSAnthony Liguori {
7582f28d2ffSAnthony Liguori Object *obj;
7594c880f36SRichard Henderson size_t size, align;
7604c880f36SRichard Henderson void (*obj_free)(void *);
7612f28d2ffSAnthony Liguori
7622f28d2ffSAnthony Liguori g_assert(type != NULL);
763ac451033SIgor Mitsyanko type_initialize(type);
7642f28d2ffSAnthony Liguori
7654c880f36SRichard Henderson size = type->instance_size;
7664c880f36SRichard Henderson align = type->instance_align;
7674c880f36SRichard Henderson
7684c880f36SRichard Henderson /*
7694c880f36SRichard Henderson * Do not use qemu_memalign unless required. Depending on the
7704c880f36SRichard Henderson * implementation, extra alignment implies extra overhead.
7714c880f36SRichard Henderson */
7724c880f36SRichard Henderson if (likely(align <= __alignof__(qemu_max_align_t))) {
7734c880f36SRichard Henderson obj = g_malloc(size);
7744c880f36SRichard Henderson obj_free = g_free;
7754c880f36SRichard Henderson } else {
7764c880f36SRichard Henderson obj = qemu_memalign(align, size);
7774c880f36SRichard Henderson obj_free = qemu_vfree;
7784c880f36SRichard Henderson }
7794c880f36SRichard Henderson
7804c880f36SRichard Henderson object_initialize_with_type(obj, size, type);
7814c880f36SRichard Henderson obj->free = obj_free;
7822f28d2ffSAnthony Liguori
7832f28d2ffSAnthony Liguori return obj;
7842f28d2ffSAnthony Liguori }
7852f28d2ffSAnthony Liguori
object_new_with_class(ObjectClass * klass)7863c75e12eSPaolo Bonzini Object *object_new_with_class(ObjectClass *klass)
7873c75e12eSPaolo Bonzini {
7883c75e12eSPaolo Bonzini return object_new_with_type(klass->type);
7893c75e12eSPaolo Bonzini }
7903c75e12eSPaolo Bonzini
object_new(const char * typename)7912f28d2ffSAnthony Liguori Object *object_new(const char *typename)
7922f28d2ffSAnthony Liguori {
793*02009a12SPaolo Bonzini TypeImpl *ti = type_get_or_load_by_name(typename, &error_fatal);
7942f28d2ffSAnthony Liguori
7952f28d2ffSAnthony Liguori return object_new_with_type(ti);
7962f28d2ffSAnthony Liguori }
7972f28d2ffSAnthony Liguori
798a31bdae5SDaniel P. Berrange
object_new_with_props(const char * typename,Object * parent,const char * id,Error ** errp,...)799a31bdae5SDaniel P. Berrange Object *object_new_with_props(const char *typename,
800a31bdae5SDaniel P. Berrange Object *parent,
801a31bdae5SDaniel P. Berrange const char *id,
802a31bdae5SDaniel P. Berrange Error **errp,
803a31bdae5SDaniel P. Berrange ...)
804a31bdae5SDaniel P. Berrange {
805a31bdae5SDaniel P. Berrange va_list vargs;
806a31bdae5SDaniel P. Berrange Object *obj;
807a31bdae5SDaniel P. Berrange
808a31bdae5SDaniel P. Berrange va_start(vargs, errp);
809a31bdae5SDaniel P. Berrange obj = object_new_with_propv(typename, parent, id, errp, vargs);
810a31bdae5SDaniel P. Berrange va_end(vargs);
811a31bdae5SDaniel P. Berrange
812a31bdae5SDaniel P. Berrange return obj;
813a31bdae5SDaniel P. Berrange }
814a31bdae5SDaniel P. Berrange
815a31bdae5SDaniel P. Berrange
object_new_with_propv(const char * typename,Object * parent,const char * id,Error ** errp,va_list vargs)816a31bdae5SDaniel P. Berrange Object *object_new_with_propv(const char *typename,
817a31bdae5SDaniel P. Berrange Object *parent,
818a31bdae5SDaniel P. Berrange const char *id,
819a31bdae5SDaniel P. Berrange Error **errp,
820a31bdae5SDaniel P. Berrange va_list vargs)
821a31bdae5SDaniel P. Berrange {
822a31bdae5SDaniel P. Berrange Object *obj;
823a31bdae5SDaniel P. Berrange ObjectClass *klass;
8243650b2deSMarc-André Lureau UserCreatable *uc;
825a31bdae5SDaniel P. Berrange
826a31bdae5SDaniel P. Berrange klass = object_class_by_name(typename);
827a31bdae5SDaniel P. Berrange if (!klass) {
828a31bdae5SDaniel P. Berrange error_setg(errp, "invalid object type: %s", typename);
829a31bdae5SDaniel P. Berrange return NULL;
830a31bdae5SDaniel P. Berrange }
831a31bdae5SDaniel P. Berrange
832a31bdae5SDaniel P. Berrange if (object_class_is_abstract(klass)) {
833a31bdae5SDaniel P. Berrange error_setg(errp, "object type '%s' is abstract", typename);
834a31bdae5SDaniel P. Berrange return NULL;
835a31bdae5SDaniel P. Berrange }
83666e1155aSWei Yang obj = object_new_with_type(klass->type);
837a31bdae5SDaniel P. Berrange
838b783f54dSMarkus Armbruster if (!object_set_propv(obj, errp, vargs)) {
839a31bdae5SDaniel P. Berrange goto error;
840a31bdae5SDaniel P. Berrange }
841a31bdae5SDaniel P. Berrange
8426134d752SDaniel P. Berrangé if (id != NULL) {
843d2623129SMarkus Armbruster object_property_add_child(parent, id, obj);
8446134d752SDaniel P. Berrangé }
845a31bdae5SDaniel P. Berrange
8463650b2deSMarc-André Lureau uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
8473650b2deSMarc-André Lureau if (uc) {
848992861fbSMarkus Armbruster if (!user_creatable_complete(uc, errp)) {
8496134d752SDaniel P. Berrangé if (id != NULL) {
850a31bdae5SDaniel P. Berrange object_unparent(obj);
8516134d752SDaniel P. Berrangé }
852a31bdae5SDaniel P. Berrange goto error;
853a31bdae5SDaniel P. Berrange }
854a31bdae5SDaniel P. Berrange }
855a31bdae5SDaniel P. Berrange
856688ffbb4SPhilippe Mathieu-Daudé object_unref(obj);
857a31bdae5SDaniel P. Berrange return obj;
858a31bdae5SDaniel P. Berrange
859a31bdae5SDaniel P. Berrange error:
860a31bdae5SDaniel P. Berrange object_unref(obj);
861a31bdae5SDaniel P. Berrange return NULL;
862a31bdae5SDaniel P. Berrange }
863a31bdae5SDaniel P. Berrange
864a31bdae5SDaniel P. Berrange
object_set_props(Object * obj,Error ** errp,...)865b783f54dSMarkus Armbruster bool object_set_props(Object *obj,
866a31bdae5SDaniel P. Berrange Error **errp,
867a31bdae5SDaniel P. Berrange ...)
868a31bdae5SDaniel P. Berrange {
869a31bdae5SDaniel P. Berrange va_list vargs;
870b783f54dSMarkus Armbruster bool ret;
871a31bdae5SDaniel P. Berrange
872a31bdae5SDaniel P. Berrange va_start(vargs, errp);
873a31bdae5SDaniel P. Berrange ret = object_set_propv(obj, errp, vargs);
874a31bdae5SDaniel P. Berrange va_end(vargs);
875a31bdae5SDaniel P. Berrange
876a31bdae5SDaniel P. Berrange return ret;
877a31bdae5SDaniel P. Berrange }
878a31bdae5SDaniel P. Berrange
879a31bdae5SDaniel P. Berrange
object_set_propv(Object * obj,Error ** errp,va_list vargs)880b783f54dSMarkus Armbruster bool object_set_propv(Object *obj,
881a31bdae5SDaniel P. Berrange Error **errp,
882a31bdae5SDaniel P. Berrange va_list vargs)
883a31bdae5SDaniel P. Berrange {
884a31bdae5SDaniel P. Berrange const char *propname;
885a31bdae5SDaniel P. Berrange
886a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *);
887a31bdae5SDaniel P. Berrange while (propname != NULL) {
888a31bdae5SDaniel P. Berrange const char *value = va_arg(vargs, char *);
889a31bdae5SDaniel P. Berrange
890a31bdae5SDaniel P. Berrange g_assert(value != NULL);
891668f62ecSMarkus Armbruster if (!object_property_parse(obj, propname, value, errp)) {
892b783f54dSMarkus Armbruster return false;
893a31bdae5SDaniel P. Berrange }
894a31bdae5SDaniel P. Berrange propname = va_arg(vargs, char *);
895a31bdae5SDaniel P. Berrange }
896a31bdae5SDaniel P. Berrange
897b783f54dSMarkus Armbruster return true;
898a31bdae5SDaniel P. Berrange }
899a31bdae5SDaniel P. Berrange
900a31bdae5SDaniel P. Berrange
object_dynamic_cast(Object * obj,const char * typename)9012f28d2ffSAnthony Liguori Object *object_dynamic_cast(Object *obj, const char *typename)
9022f28d2ffSAnthony Liguori {
903b7f43fe4SPaolo Bonzini if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
904acc4af3fSPaolo Bonzini return obj;
905acc4af3fSPaolo Bonzini }
906acc4af3fSPaolo Bonzini
9072f28d2ffSAnthony Liguori return NULL;
9082f28d2ffSAnthony Liguori }
9092f28d2ffSAnthony Liguori
object_dynamic_cast_assert(Object * obj,const char * typename,const char * file,int line,const char * func)910be17f18bSPaolo Bonzini Object *object_dynamic_cast_assert(Object *obj, const char *typename,
911be17f18bSPaolo Bonzini const char *file, int line, const char *func)
9122f28d2ffSAnthony Liguori {
913fa131d94SPaolo Bonzini trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
914fa131d94SPaolo Bonzini typename, file, line, func);
915fa131d94SPaolo Bonzini
9163556c233SPaolo Bonzini #ifdef CONFIG_QOM_CAST_DEBUG
91703587328SAnthony Liguori int i;
91803587328SAnthony Liguori Object *inst;
91903587328SAnthony Liguori
92095916abcSPeter Crosthwaite for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
921d73415a3SStefan Hajnoczi if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) {
92203587328SAnthony Liguori goto out;
92303587328SAnthony Liguori }
92403587328SAnthony Liguori }
92503587328SAnthony Liguori
92603587328SAnthony Liguori inst = object_dynamic_cast(obj, typename);
9272f28d2ffSAnthony Liguori
928b7f43fe4SPaolo Bonzini if (!inst && obj) {
929be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
930be17f18bSPaolo Bonzini file, line, func, obj, typename);
9312f28d2ffSAnthony Liguori abort();
9322f28d2ffSAnthony Liguori }
9332f28d2ffSAnthony Liguori
9343556c233SPaolo Bonzini assert(obj == inst);
93503587328SAnthony Liguori
93695916abcSPeter Crosthwaite if (obj && obj == inst) {
93703587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
938d73415a3SStefan Hajnoczi qatomic_set(&obj->class->object_cast_cache[i - 1],
939d73415a3SStefan Hajnoczi qatomic_read(&obj->class->object_cast_cache[i]));
94003587328SAnthony Liguori }
941d73415a3SStefan Hajnoczi qatomic_set(&obj->class->object_cast_cache[i - 1], typename);
94203587328SAnthony Liguori }
94303587328SAnthony Liguori
94403587328SAnthony Liguori out:
9453556c233SPaolo Bonzini #endif
9463556c233SPaolo Bonzini return obj;
9472f28d2ffSAnthony Liguori }
9482f28d2ffSAnthony Liguori
object_class_dynamic_cast(ObjectClass * class,const char * typename)9492f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast(ObjectClass *class,
9502f28d2ffSAnthony Liguori const char *typename)
9512f28d2ffSAnthony Liguori {
95233e95c63SAnthony Liguori ObjectClass *ret = NULL;
953bf0fda34SPaolo Bonzini TypeImpl *target_type;
954bf0fda34SPaolo Bonzini TypeImpl *type;
9552f28d2ffSAnthony Liguori
956bf0fda34SPaolo Bonzini if (!class) {
957bf0fda34SPaolo Bonzini return NULL;
958bf0fda34SPaolo Bonzini }
959bf0fda34SPaolo Bonzini
960793c96b5SPaolo Bonzini /* A simple fast path that can trigger a lot for leaf classes. */
961bf0fda34SPaolo Bonzini type = class->type;
962793c96b5SPaolo Bonzini if (type->name == typename) {
963793c96b5SPaolo Bonzini return class;
964793c96b5SPaolo Bonzini }
965793c96b5SPaolo Bonzini
966144d80f6SPaolo Bonzini target_type = type_get_by_name_noload(typename);
9679ab880b3SAlexander Graf if (!target_type) {
9689ab880b3SAlexander Graf /* target class type unknown, so fail the cast */
9699ab880b3SAlexander Graf return NULL;
9709ab880b3SAlexander Graf }
9719ab880b3SAlexander Graf
97200e2ceaeSPeter Crosthwaite if (type->class->interfaces &&
97300e2ceaeSPeter Crosthwaite type_is_ancestor(target_type, type_interface)) {
97433e95c63SAnthony Liguori int found = 0;
97533e95c63SAnthony Liguori GSList *i;
97633e95c63SAnthony Liguori
97733e95c63SAnthony Liguori for (i = class->interfaces; i; i = i->next) {
97833e95c63SAnthony Liguori ObjectClass *target_class = i->data;
97933e95c63SAnthony Liguori
98033e95c63SAnthony Liguori if (type_is_ancestor(target_class->type, target_type)) {
98133e95c63SAnthony Liguori ret = target_class;
98233e95c63SAnthony Liguori found++;
98333e95c63SAnthony Liguori }
9842f28d2ffSAnthony Liguori }
9852f28d2ffSAnthony Liguori
98633e95c63SAnthony Liguori /* The match was ambiguous, don't allow a cast */
98733e95c63SAnthony Liguori if (found > 1) {
98833e95c63SAnthony Liguori ret = NULL;
98933e95c63SAnthony Liguori }
99033e95c63SAnthony Liguori } else if (type_is_ancestor(type, target_type)) {
99133e95c63SAnthony Liguori ret = class;
9922f28d2ffSAnthony Liguori }
9932f28d2ffSAnthony Liguori
99433e95c63SAnthony Liguori return ret;
9952f28d2ffSAnthony Liguori }
9962f28d2ffSAnthony Liguori
object_class_dynamic_cast_assert(ObjectClass * class,const char * typename,const char * file,int line,const char * func)9972f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
998be17f18bSPaolo Bonzini const char *typename,
999be17f18bSPaolo Bonzini const char *file, int line,
1000be17f18bSPaolo Bonzini const char *func)
10012f28d2ffSAnthony Liguori {
1002fa131d94SPaolo Bonzini ObjectClass *ret;
10032f28d2ffSAnthony Liguori
1004fa131d94SPaolo Bonzini trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
1005fa131d94SPaolo Bonzini typename, file, line, func);
1006fa131d94SPaolo Bonzini
100703587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG
100803587328SAnthony Liguori int i;
100903587328SAnthony Liguori
10109d6a3d58SPeter Crosthwaite for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
1011d73415a3SStefan Hajnoczi if (qatomic_read(&class->class_cast_cache[i]) == typename) {
101203587328SAnthony Liguori ret = class;
101303587328SAnthony Liguori goto out;
101403587328SAnthony Liguori }
101503587328SAnthony Liguori }
101603587328SAnthony Liguori #else
10179d6a3d58SPeter Crosthwaite if (!class || !class->interfaces) {
10183556c233SPaolo Bonzini return class;
10193556c233SPaolo Bonzini }
10203556c233SPaolo Bonzini #endif
10213556c233SPaolo Bonzini
1022fa131d94SPaolo Bonzini ret = object_class_dynamic_cast(class, typename);
1023bf0fda34SPaolo Bonzini if (!ret && class) {
1024be17f18bSPaolo Bonzini fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
1025be17f18bSPaolo Bonzini file, line, func, class, typename);
10262f28d2ffSAnthony Liguori abort();
10272f28d2ffSAnthony Liguori }
10282f28d2ffSAnthony Liguori
102903587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG
10309d6a3d58SPeter Crosthwaite if (class && ret == class) {
103103587328SAnthony Liguori for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
1032d73415a3SStefan Hajnoczi qatomic_set(&class->class_cast_cache[i - 1],
1033d73415a3SStefan Hajnoczi qatomic_read(&class->class_cast_cache[i]));
103403587328SAnthony Liguori }
1035d73415a3SStefan Hajnoczi qatomic_set(&class->class_cast_cache[i - 1], typename);
103603587328SAnthony Liguori }
103703587328SAnthony Liguori out:
103803587328SAnthony Liguori #endif
10392f28d2ffSAnthony Liguori return ret;
10402f28d2ffSAnthony Liguori }
10412f28d2ffSAnthony Liguori
object_get_typename(const Object * obj)10428f5d58efSIgor Mammedov const char *object_get_typename(const Object *obj)
10432f28d2ffSAnthony Liguori {
10442f28d2ffSAnthony Liguori return obj->class->type->name;
10452f28d2ffSAnthony Liguori }
10462f28d2ffSAnthony Liguori
object_get_class(Object * obj)10472f28d2ffSAnthony Liguori ObjectClass *object_get_class(Object *obj)
10482f28d2ffSAnthony Liguori {
10492f28d2ffSAnthony Liguori return obj->class;
10502f28d2ffSAnthony Liguori }
10512f28d2ffSAnthony Liguori
object_class_is_abstract(ObjectClass * klass)105217862378SAndreas Färber bool object_class_is_abstract(ObjectClass *klass)
105317862378SAndreas Färber {
105417862378SAndreas Färber return klass->type->abstract;
105517862378SAndreas Färber }
105617862378SAndreas Färber
object_class_get_name(ObjectClass * klass)10572f28d2ffSAnthony Liguori const char *object_class_get_name(ObjectClass *klass)
10582f28d2ffSAnthony Liguori {
10592f28d2ffSAnthony Liguori return klass->type->name;
10602f28d2ffSAnthony Liguori }
10612f28d2ffSAnthony Liguori
object_class_by_name(const char * typename)10622f28d2ffSAnthony Liguori ObjectClass *object_class_by_name(const char *typename)
10632f28d2ffSAnthony Liguori {
1064144d80f6SPaolo Bonzini TypeImpl *type = type_get_by_name_noload(typename);
10652f28d2ffSAnthony Liguori
10662f28d2ffSAnthony Liguori if (!type) {
10672f28d2ffSAnthony Liguori return NULL;
10682f28d2ffSAnthony Liguori }
10692f28d2ffSAnthony Liguori
1070ac451033SIgor Mitsyanko type_initialize(type);
10712f28d2ffSAnthony Liguori
10722f28d2ffSAnthony Liguori return type->class;
10732f28d2ffSAnthony Liguori }
10742f28d2ffSAnthony Liguori
module_object_class_by_name(const char * typename)10750f8198f1SGerd Hoffmann ObjectClass *module_object_class_by_name(const char *typename)
10760f8198f1SGerd Hoffmann {
1077144d80f6SPaolo Bonzini TypeImpl *type = type_get_or_load_by_name(typename, NULL);
10780f8198f1SGerd Hoffmann
1079144d80f6SPaolo Bonzini if (!type) {
1080144d80f6SPaolo Bonzini return NULL;
1081c551fb0bSClaudio Fontana }
1082144d80f6SPaolo Bonzini
1083144d80f6SPaolo Bonzini type_initialize(type);
1084144d80f6SPaolo Bonzini
1085144d80f6SPaolo Bonzini return type->class;
10860f8198f1SGerd Hoffmann }
10870f8198f1SGerd Hoffmann
object_class_get_parent(ObjectClass * class)1088e7cce67fSPaolo Bonzini ObjectClass *object_class_get_parent(ObjectClass *class)
1089e7cce67fSPaolo Bonzini {
1090e7cce67fSPaolo Bonzini TypeImpl *type = type_get_parent(class->type);
1091e7cce67fSPaolo Bonzini
1092e7cce67fSPaolo Bonzini if (!type) {
1093e7cce67fSPaolo Bonzini return NULL;
1094e7cce67fSPaolo Bonzini }
1095e7cce67fSPaolo Bonzini
1096e7cce67fSPaolo Bonzini type_initialize(type);
1097e7cce67fSPaolo Bonzini
1098e7cce67fSPaolo Bonzini return type->class;
1099e7cce67fSPaolo Bonzini }
1100e7cce67fSPaolo Bonzini
11012f28d2ffSAnthony Liguori typedef struct OCFData
11022f28d2ffSAnthony Liguori {
11032f28d2ffSAnthony Liguori void (*fn)(ObjectClass *klass, void *opaque);
110493c511a1SAnthony Liguori const char *implements_type;
110593c511a1SAnthony Liguori bool include_abstract;
11062f28d2ffSAnthony Liguori void *opaque;
11072f28d2ffSAnthony Liguori } OCFData;
11082f28d2ffSAnthony Liguori
object_class_foreach_tramp(gpointer key,gpointer value,gpointer opaque)11092f28d2ffSAnthony Liguori static void object_class_foreach_tramp(gpointer key, gpointer value,
11102f28d2ffSAnthony Liguori gpointer opaque)
11112f28d2ffSAnthony Liguori {
11122f28d2ffSAnthony Liguori OCFData *data = opaque;
11132f28d2ffSAnthony Liguori TypeImpl *type = value;
111493c511a1SAnthony Liguori ObjectClass *k;
11152f28d2ffSAnthony Liguori
1116ac451033SIgor Mitsyanko type_initialize(type);
111793c511a1SAnthony Liguori k = type->class;
11182f28d2ffSAnthony Liguori
111993c511a1SAnthony Liguori if (!data->include_abstract && type->abstract) {
112093c511a1SAnthony Liguori return;
112193c511a1SAnthony Liguori }
112293c511a1SAnthony Liguori
112393c511a1SAnthony Liguori if (data->implements_type &&
112493c511a1SAnthony Liguori !object_class_dynamic_cast(k, data->implements_type)) {
112593c511a1SAnthony Liguori return;
112693c511a1SAnthony Liguori }
112793c511a1SAnthony Liguori
112893c511a1SAnthony Liguori data->fn(k, data->opaque);
11292f28d2ffSAnthony Liguori }
11302f28d2ffSAnthony Liguori
object_class_foreach(void (* fn)(ObjectClass * klass,void * opaque),const char * implements_type,bool include_abstract,void * opaque)11312f28d2ffSAnthony Liguori void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
113293c511a1SAnthony Liguori const char *implements_type, bool include_abstract,
11332f28d2ffSAnthony Liguori void *opaque)
11342f28d2ffSAnthony Liguori {
113593c511a1SAnthony Liguori OCFData data = { fn, implements_type, include_abstract, opaque };
11362f28d2ffSAnthony Liguori
1137f54c19caSHervé Poussineau enumerating_types = true;
11382f28d2ffSAnthony Liguori g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
1139f54c19caSHervé Poussineau enumerating_types = false;
11402f28d2ffSAnthony Liguori }
114157c9fafeSAnthony Liguori
do_object_child_foreach(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque,bool recurse)1142d714b8deSPeter Crosthwaite static int do_object_child_foreach(Object *obj,
1143d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque),
1144d714b8deSPeter Crosthwaite void *opaque, bool recurse)
114532efc535SPaolo Bonzini {
1146b604a854SPavel Fedin GHashTableIter iter;
1147b604a854SPavel Fedin ObjectProperty *prop;
114832efc535SPaolo Bonzini int ret = 0;
114932efc535SPaolo Bonzini
1150b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->properties);
1151b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
115232efc535SPaolo Bonzini if (object_property_is_child(prop)) {
1153d714b8deSPeter Crosthwaite Object *child = prop->opaque;
1154d714b8deSPeter Crosthwaite
1155d714b8deSPeter Crosthwaite ret = fn(child, opaque);
115632efc535SPaolo Bonzini if (ret != 0) {
115732efc535SPaolo Bonzini break;
115832efc535SPaolo Bonzini }
1159d714b8deSPeter Crosthwaite if (recurse) {
11604a39181dSCédric Le Goater ret = do_object_child_foreach(child, fn, opaque, true);
11614a39181dSCédric Le Goater if (ret != 0) {
11624a39181dSCédric Le Goater break;
11634a39181dSCédric Le Goater }
1164d714b8deSPeter Crosthwaite }
116532efc535SPaolo Bonzini }
116632efc535SPaolo Bonzini }
116732efc535SPaolo Bonzini return ret;
116832efc535SPaolo Bonzini }
116932efc535SPaolo Bonzini
object_child_foreach(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque)1170d714b8deSPeter Crosthwaite int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
1171d714b8deSPeter Crosthwaite void *opaque)
1172d714b8deSPeter Crosthwaite {
1173d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, false);
1174d714b8deSPeter Crosthwaite }
1175d714b8deSPeter Crosthwaite
object_child_foreach_recursive(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque)1176d714b8deSPeter Crosthwaite int object_child_foreach_recursive(Object *obj,
1177d714b8deSPeter Crosthwaite int (*fn)(Object *child, void *opaque),
1178d714b8deSPeter Crosthwaite void *opaque)
1179d714b8deSPeter Crosthwaite {
1180d714b8deSPeter Crosthwaite return do_object_child_foreach(obj, fn, opaque, true);
1181d714b8deSPeter Crosthwaite }
1182d714b8deSPeter Crosthwaite
object_class_get_list_tramp(ObjectClass * klass,void * opaque)1183418ba9e5SAndreas Färber static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
1184418ba9e5SAndreas Färber {
1185418ba9e5SAndreas Färber GSList **list = opaque;
1186418ba9e5SAndreas Färber
1187418ba9e5SAndreas Färber *list = g_slist_prepend(*list, klass);
1188418ba9e5SAndreas Färber }
1189418ba9e5SAndreas Färber
object_class_get_list(const char * implements_type,bool include_abstract)1190418ba9e5SAndreas Färber GSList *object_class_get_list(const char *implements_type,
1191418ba9e5SAndreas Färber bool include_abstract)
1192418ba9e5SAndreas Färber {
1193418ba9e5SAndreas Färber GSList *list = NULL;
1194418ba9e5SAndreas Färber
1195418ba9e5SAndreas Färber object_class_foreach(object_class_get_list_tramp,
1196418ba9e5SAndreas Färber implements_type, include_abstract, &list);
1197418ba9e5SAndreas Färber return list;
1198418ba9e5SAndreas Färber }
1199418ba9e5SAndreas Färber
object_class_cmp(gconstpointer a,gconstpointer b)120047c66009SPaolo Bonzini static gint object_class_cmp(gconstpointer a, gconstpointer b)
120147c66009SPaolo Bonzini {
120247c66009SPaolo Bonzini return strcasecmp(object_class_get_name((ObjectClass *)a),
120347c66009SPaolo Bonzini object_class_get_name((ObjectClass *)b));
120447c66009SPaolo Bonzini }
120547c66009SPaolo Bonzini
object_class_get_list_sorted(const char * implements_type,bool include_abstract)120647c66009SPaolo Bonzini GSList *object_class_get_list_sorted(const char *implements_type,
120747c66009SPaolo Bonzini bool include_abstract)
120847c66009SPaolo Bonzini {
120947c66009SPaolo Bonzini return g_slist_sort(object_class_get_list(implements_type, include_abstract),
121047c66009SPaolo Bonzini object_class_cmp);
121147c66009SPaolo Bonzini }
121247c66009SPaolo Bonzini
object_ref(void * objptr)1213c5a61e5aSDaniel P. Berrangé Object *object_ref(void *objptr)
121457c9fafeSAnthony Liguori {
1215c5a61e5aSDaniel P. Berrangé Object *obj = OBJECT(objptr);
1216e3682878SMichael S. Tsirkin uint32_t ref;
1217e3682878SMichael S. Tsirkin
12188ffad850SPeter Crosthwaite if (!obj) {
1219b77ade9bSMarc-André Lureau return NULL;
12208ffad850SPeter Crosthwaite }
1221e3682878SMichael S. Tsirkin ref = qatomic_fetch_inc(&obj->ref);
1222e3682878SMichael S. Tsirkin /* Assert waaay before the integer overflows */
1223e3682878SMichael S. Tsirkin g_assert(ref < INT_MAX);
1224b77ade9bSMarc-André Lureau return obj;
122557c9fafeSAnthony Liguori }
122657c9fafeSAnthony Liguori
object_unref(void * objptr)1227c5a61e5aSDaniel P. Berrangé void object_unref(void *objptr)
122857c9fafeSAnthony Liguori {
1229c5a61e5aSDaniel P. Berrangé Object *obj = OBJECT(objptr);
12308ffad850SPeter Crosthwaite if (!obj) {
12318ffad850SPeter Crosthwaite return;
12328ffad850SPeter Crosthwaite }
1233719a3077SMarkus Armbruster g_assert(obj->ref > 0);
123457c9fafeSAnthony Liguori
123557c9fafeSAnthony Liguori /* parent always holds a reference to its children */
1236d73415a3SStefan Hajnoczi if (qatomic_fetch_dec(&obj->ref) == 1) {
123757c9fafeSAnthony Liguori object_finalize(obj);
123857c9fafeSAnthony Liguori }
123957c9fafeSAnthony Liguori }
124057c9fafeSAnthony Liguori
1241db57fef1SEric Auger ObjectProperty *
object_property_try_add(Object * obj,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque,Error ** errp)1242d2623129SMarkus Armbruster object_property_try_add(Object *obj, const char *name, const char *type,
124357c9fafeSAnthony Liguori ObjectPropertyAccessor *get,
124457c9fafeSAnthony Liguori ObjectPropertyAccessor *set,
124557c9fafeSAnthony Liguori ObjectPropertyRelease *release,
124657c9fafeSAnthony Liguori void *opaque, Error **errp)
124757c9fafeSAnthony Liguori {
124854852b03SPeter Maydell ObjectProperty *prop;
124933965904SPeter Crosthwaite size_t name_len = strlen(name);
125033965904SPeter Crosthwaite
125133965904SPeter Crosthwaite if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
125233965904SPeter Crosthwaite int i;
12531bf8b88fSAni Sinha ObjectProperty *ret = NULL;
125433965904SPeter Crosthwaite char *name_no_array = g_strdup(name);
125533965904SPeter Crosthwaite
125633965904SPeter Crosthwaite name_no_array[name_len - 3] = '\0';
12571bf8b88fSAni Sinha for (i = 0; i < INT16_MAX; ++i) {
125833965904SPeter Crosthwaite char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
125933965904SPeter Crosthwaite
1260d2623129SMarkus Armbruster ret = object_property_try_add(obj, full_name, type, get, set,
126133965904SPeter Crosthwaite release, opaque, NULL);
126233965904SPeter Crosthwaite g_free(full_name);
126333965904SPeter Crosthwaite if (ret) {
126433965904SPeter Crosthwaite break;
126533965904SPeter Crosthwaite }
126633965904SPeter Crosthwaite }
126733965904SPeter Crosthwaite g_free(name_no_array);
12681bf8b88fSAni Sinha assert(ret);
126933965904SPeter Crosthwaite return ret;
127033965904SPeter Crosthwaite }
127154852b03SPeter Maydell
1272efba1595SDaniel P. Berrangé if (object_property_find(obj, name) != NULL) {
1273d55e937dSGreg Kurz error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
1274d55e937dSGreg Kurz name, object_get_typename(obj));
127564607d08SPaolo Bonzini return NULL;
127654852b03SPeter Maydell }
127754852b03SPeter Maydell
127854852b03SPeter Maydell prop = g_malloc0(sizeof(*prop));
127957c9fafeSAnthony Liguori
128057c9fafeSAnthony Liguori prop->name = g_strdup(name);
128157c9fafeSAnthony Liguori prop->type = g_strdup(type);
128257c9fafeSAnthony Liguori
128357c9fafeSAnthony Liguori prop->get = get;
128457c9fafeSAnthony Liguori prop->set = set;
128557c9fafeSAnthony Liguori prop->release = release;
128657c9fafeSAnthony Liguori prop->opaque = opaque;
128757c9fafeSAnthony Liguori
1288b604a854SPavel Fedin g_hash_table_insert(obj->properties, prop->name, prop);
128964607d08SPaolo Bonzini return prop;
129057c9fafeSAnthony Liguori }
129157c9fafeSAnthony Liguori
129216bf7f52SDaniel P. Berrange ObjectProperty *
object_property_add(Object * obj,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque)1293d2623129SMarkus Armbruster object_property_add(Object *obj, const char *name, const char *type,
1294d2623129SMarkus Armbruster ObjectPropertyAccessor *get,
1295d2623129SMarkus Armbruster ObjectPropertyAccessor *set,
1296d2623129SMarkus Armbruster ObjectPropertyRelease *release,
1297d2623129SMarkus Armbruster void *opaque)
1298d2623129SMarkus Armbruster {
1299d2623129SMarkus Armbruster return object_property_try_add(obj, name, type, get, set, release,
1300d2623129SMarkus Armbruster opaque, &error_abort);
1301d2623129SMarkus Armbruster }
1302d2623129SMarkus Armbruster
1303d2623129SMarkus Armbruster ObjectProperty *
object_class_property_add(ObjectClass * klass,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque)130416bf7f52SDaniel P. Berrange object_class_property_add(ObjectClass *klass,
130516bf7f52SDaniel P. Berrange const char *name,
130616bf7f52SDaniel P. Berrange const char *type,
130716bf7f52SDaniel P. Berrange ObjectPropertyAccessor *get,
130816bf7f52SDaniel P. Berrange ObjectPropertyAccessor *set,
130916bf7f52SDaniel P. Berrange ObjectPropertyRelease *release,
1310d2623129SMarkus Armbruster void *opaque)
131116bf7f52SDaniel P. Berrange {
131216bf7f52SDaniel P. Berrange ObjectProperty *prop;
131316bf7f52SDaniel P. Berrange
1314efba1595SDaniel P. Berrangé assert(!object_class_property_find(klass, name));
131516bf7f52SDaniel P. Berrange
131616bf7f52SDaniel P. Berrange prop = g_malloc0(sizeof(*prop));
131716bf7f52SDaniel P. Berrange
131816bf7f52SDaniel P. Berrange prop->name = g_strdup(name);
131916bf7f52SDaniel P. Berrange prop->type = g_strdup(type);
132016bf7f52SDaniel P. Berrange
132116bf7f52SDaniel P. Berrange prop->get = get;
132216bf7f52SDaniel P. Berrange prop->set = set;
132316bf7f52SDaniel P. Berrange prop->release = release;
132416bf7f52SDaniel P. Berrange prop->opaque = opaque;
132516bf7f52SDaniel P. Berrange
1326ba806ffbSMarc-André Lureau g_hash_table_insert(klass->properties, prop->name, prop);
132716bf7f52SDaniel P. Berrange
132816bf7f52SDaniel P. Berrange return prop;
132916bf7f52SDaniel P. Berrange }
133016bf7f52SDaniel P. Berrange
object_property_find(Object * obj,const char * name)1331efba1595SDaniel P. Berrangé ObjectProperty *object_property_find(Object *obj, const char *name)
133257c9fafeSAnthony Liguori {
133357c9fafeSAnthony Liguori ObjectProperty *prop;
133416bf7f52SDaniel P. Berrange ObjectClass *klass = object_get_class(obj);
133516bf7f52SDaniel P. Berrange
1336efba1595SDaniel P. Berrangé prop = object_class_property_find(klass, name);
133716bf7f52SDaniel P. Berrange if (prop) {
133816bf7f52SDaniel P. Berrange return prop;
133916bf7f52SDaniel P. Berrange }
134057c9fafeSAnthony Liguori
1341efba1595SDaniel P. Berrangé return g_hash_table_lookup(obj->properties, name);
134257c9fafeSAnthony Liguori }
134357c9fafeSAnthony Liguori
object_property_find_err(Object * obj,const char * name,Error ** errp)1344efba1595SDaniel P. Berrangé ObjectProperty *object_property_find_err(Object *obj, const char *name,
1345efba1595SDaniel P. Berrangé Error **errp)
1346efba1595SDaniel P. Berrangé {
1347efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find(obj, name);
1348efba1595SDaniel P. Berrangé if (!prop) {
13494d9c7c84SPhilippe Mathieu-Daudé error_setg(errp, "Property '%s.%s' not found",
13504d9c7c84SPhilippe Mathieu-Daudé object_get_typename(obj), name);
1351efba1595SDaniel P. Berrangé }
1352efba1595SDaniel P. Berrangé return prop;
135357c9fafeSAnthony Liguori }
135457c9fafeSAnthony Liguori
object_property_iter_init(ObjectPropertyIterator * iter,Object * obj)13557746abd8SDaniel P. Berrange void object_property_iter_init(ObjectPropertyIterator *iter,
13567746abd8SDaniel P. Berrange Object *obj)
1357a00c9482SDaniel P. Berrange {
13587746abd8SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, obj->properties);
13597746abd8SDaniel P. Berrange iter->nextclass = object_get_class(obj);
1360a00c9482SDaniel P. Berrange }
1361a00c9482SDaniel P. Berrange
object_property_iter_next(ObjectPropertyIterator * iter)1362a00c9482SDaniel P. Berrange ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1363a00c9482SDaniel P. Berrange {
1364b604a854SPavel Fedin gpointer key, val;
136516bf7f52SDaniel P. Berrange while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
136616bf7f52SDaniel P. Berrange if (!iter->nextclass) {
1367b604a854SPavel Fedin return NULL;
1368a00c9482SDaniel P. Berrange }
136916bf7f52SDaniel P. Berrange g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
137016bf7f52SDaniel P. Berrange iter->nextclass = object_class_get_parent(iter->nextclass);
137116bf7f52SDaniel P. Berrange }
1372b604a854SPavel Fedin return val;
1373a00c9482SDaniel P. Berrange }
1374a00c9482SDaniel P. Berrange
object_class_property_iter_init(ObjectPropertyIterator * iter,ObjectClass * klass)1375961c47bbSAlexey Kardashevskiy void object_class_property_iter_init(ObjectPropertyIterator *iter,
1376961c47bbSAlexey Kardashevskiy ObjectClass *klass)
1377961c47bbSAlexey Kardashevskiy {
1378961c47bbSAlexey Kardashevskiy g_hash_table_iter_init(&iter->iter, klass->properties);
1379684546d8SMarc-André Lureau iter->nextclass = object_class_get_parent(klass);
1380961c47bbSAlexey Kardashevskiy }
1381961c47bbSAlexey Kardashevskiy
object_class_property_find(ObjectClass * klass,const char * name)1382efba1595SDaniel P. Berrangé ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
138316bf7f52SDaniel P. Berrange {
138416bf7f52SDaniel P. Berrange ObjectClass *parent_klass;
138516bf7f52SDaniel P. Berrange
138616bf7f52SDaniel P. Berrange parent_klass = object_class_get_parent(klass);
138716bf7f52SDaniel P. Berrange if (parent_klass) {
1388efba1595SDaniel P. Berrangé ObjectProperty *prop =
1389efba1595SDaniel P. Berrangé object_class_property_find(parent_klass, name);
139016bf7f52SDaniel P. Berrange if (prop) {
139116bf7f52SDaniel P. Berrange return prop;
139216bf7f52SDaniel P. Berrange }
139316bf7f52SDaniel P. Berrange }
139416bf7f52SDaniel P. Berrange
1395efba1595SDaniel P. Berrangé return g_hash_table_lookup(klass->properties, name);
1396efba1595SDaniel P. Berrangé }
1397efba1595SDaniel P. Berrangé
object_class_property_find_err(ObjectClass * klass,const char * name,Error ** errp)1398efba1595SDaniel P. Berrangé ObjectProperty *object_class_property_find_err(ObjectClass *klass,
1399efba1595SDaniel P. Berrangé const char *name,
1400efba1595SDaniel P. Berrangé Error **errp)
1401efba1595SDaniel P. Berrangé {
1402efba1595SDaniel P. Berrangé ObjectProperty *prop = object_class_property_find(klass, name);
140316bf7f52SDaniel P. Berrange if (!prop) {
140416bf7f52SDaniel P. Berrange error_setg(errp, "Property '.%s' not found", name);
140516bf7f52SDaniel P. Berrange }
140616bf7f52SDaniel P. Berrange return prop;
140716bf7f52SDaniel P. Berrange }
140816bf7f52SDaniel P. Berrange
1409efba1595SDaniel P. Berrangé
object_property_del(Object * obj,const char * name)1410df4fe0b2SMarkus Armbruster void object_property_del(Object *obj, const char *name)
141157c9fafeSAnthony Liguori {
1412b604a854SPavel Fedin ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1413b604a854SPavel Fedin
14140866aca1SAnthony Liguori if (prop->release) {
14150866aca1SAnthony Liguori prop->release(obj, name, prop->opaque);
14160866aca1SAnthony Liguori }
1417b604a854SPavel Fedin g_hash_table_remove(obj->properties, name);
141857c9fafeSAnthony Liguori }
141957c9fafeSAnthony Liguori
object_property_get(Object * obj,const char * name,Visitor * v,Error ** errp)14206fd5bef1SMarkus Armbruster bool object_property_get(Object *obj, const char *name, Visitor *v,
142157c9fafeSAnthony Liguori Error **errp)
142257c9fafeSAnthony Liguori {
14236fd5bef1SMarkus Armbruster Error *err = NULL;
1424efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find_err(obj, name, errp);
14256fd5bef1SMarkus Armbruster
142657c9fafeSAnthony Liguori if (prop == NULL) {
14276fd5bef1SMarkus Armbruster return false;
142857c9fafeSAnthony Liguori }
142957c9fafeSAnthony Liguori
143057c9fafeSAnthony Liguori if (!prop->get) {
14313f7febc9SMarkus Armbruster error_setg(errp, "Property '%s.%s' is not readable",
14323f7febc9SMarkus Armbruster object_get_typename(obj), name);
14336fd5bef1SMarkus Armbruster return false;
143457c9fafeSAnthony Liguori }
14356fd5bef1SMarkus Armbruster prop->get(obj, v, name, prop->opaque, &err);
14366fd5bef1SMarkus Armbruster error_propagate(errp, err);
14376fd5bef1SMarkus Armbruster return !err;
143857c9fafeSAnthony Liguori }
143957c9fafeSAnthony Liguori
object_property_set(Object * obj,const char * name,Visitor * v,Error ** errp)14406fd5bef1SMarkus Armbruster bool object_property_set(Object *obj, const char *name, Visitor *v,
144157c9fafeSAnthony Liguori Error **errp)
144257c9fafeSAnthony Liguori {
1443dbc8221fSKevin Wolf ERRP_GUARD();
1444efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find_err(obj, name, errp);
14456fd5bef1SMarkus Armbruster
144657c9fafeSAnthony Liguori if (prop == NULL) {
14476fd5bef1SMarkus Armbruster return false;
144857c9fafeSAnthony Liguori }
144957c9fafeSAnthony Liguori
145057c9fafeSAnthony Liguori if (!prop->set) {
14513f7febc9SMarkus Armbruster error_setg(errp, "Property '%s.%s' is not writable",
14523f7febc9SMarkus Armbruster object_get_typename(obj), name);
14536fd5bef1SMarkus Armbruster return false;
145457c9fafeSAnthony Liguori }
1455dbc8221fSKevin Wolf prop->set(obj, v, name, prop->opaque, errp);
1456dbc8221fSKevin Wolf return !*errp;
145757c9fafeSAnthony Liguori }
145857c9fafeSAnthony Liguori
object_property_set_str(Object * obj,const char * name,const char * value,Error ** errp)14596fd5bef1SMarkus Armbruster bool object_property_set_str(Object *obj, const char *name,
14605325cc34SMarkus Armbruster const char *value, Error **errp)
14617b7b7d18SPaolo Bonzini {
14627b7b7d18SPaolo Bonzini QString *qstr = qstring_from_str(value);
14636fd5bef1SMarkus Armbruster bool ok = object_property_set_qobject(obj, name, QOBJECT(qstr), errp);
14647b7b7d18SPaolo Bonzini
1465cb3e7f08SMarc-André Lureau qobject_unref(qstr);
14666fd5bef1SMarkus Armbruster return ok;
14677b7b7d18SPaolo Bonzini }
14687b7b7d18SPaolo Bonzini
object_property_get_str(Object * obj,const char * name,Error ** errp)14697b7b7d18SPaolo Bonzini char *object_property_get_str(Object *obj, const char *name,
14707b7b7d18SPaolo Bonzini Error **errp)
14717b7b7d18SPaolo Bonzini {
14727b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp);
147326c52828SMarkus Armbruster QString *qstring;
14747b7b7d18SPaolo Bonzini char *retval;
14757b7b7d18SPaolo Bonzini
14767b7b7d18SPaolo Bonzini if (!ret) {
14777b7b7d18SPaolo Bonzini return NULL;
14787b7b7d18SPaolo Bonzini }
147926c52828SMarkus Armbruster qstring = qobject_to(QString, ret);
148026c52828SMarkus Armbruster if (!qstring) {
1481aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: string",
1482aaeafa50SPhilippe Mathieu-Daudé name);
148326c52828SMarkus Armbruster retval = NULL;
148426c52828SMarkus Armbruster } else {
148526c52828SMarkus Armbruster retval = g_strdup(qstring_get_str(qstring));
14867b7b7d18SPaolo Bonzini }
14877b7b7d18SPaolo Bonzini
1488cb3e7f08SMarc-André Lureau qobject_unref(ret);
14897b7b7d18SPaolo Bonzini return retval;
14907b7b7d18SPaolo Bonzini }
14917b7b7d18SPaolo Bonzini
object_property_set_link(Object * obj,const char * name,Object * value,Error ** errp)14926fd5bef1SMarkus Armbruster bool object_property_set_link(Object *obj, const char *name,
14935325cc34SMarkus Armbruster Object *value, Error **errp)
14941d9c5a12SPaolo Bonzini {
14956fd5bef1SMarkus Armbruster g_autofree char *path = NULL;
14966fd5bef1SMarkus Armbruster
1497d3c49316SPeter Crosthwaite if (value) {
14986fd5bef1SMarkus Armbruster path = object_get_canonical_path(value);
1499d3c49316SPeter Crosthwaite }
15006fd5bef1SMarkus Armbruster return object_property_set_str(obj, name, path ?: "", errp);
15011d9c5a12SPaolo Bonzini }
15021d9c5a12SPaolo Bonzini
object_property_get_link(Object * obj,const char * name,Error ** errp)15031d9c5a12SPaolo Bonzini Object *object_property_get_link(Object *obj, const char *name,
15041d9c5a12SPaolo Bonzini Error **errp)
15051d9c5a12SPaolo Bonzini {
15061d9c5a12SPaolo Bonzini char *str = object_property_get_str(obj, name, errp);
15071d9c5a12SPaolo Bonzini Object *target = NULL;
15081d9c5a12SPaolo Bonzini
15091d9c5a12SPaolo Bonzini if (str && *str) {
15101d9c5a12SPaolo Bonzini target = object_resolve_path(str, NULL);
15111d9c5a12SPaolo Bonzini if (!target) {
151275158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
151375158ebbSMarkus Armbruster "Device '%s' not found", str);
15141d9c5a12SPaolo Bonzini }
15151d9c5a12SPaolo Bonzini }
15161d9c5a12SPaolo Bonzini
15171d9c5a12SPaolo Bonzini g_free(str);
15181d9c5a12SPaolo Bonzini return target;
15191d9c5a12SPaolo Bonzini }
15201d9c5a12SPaolo Bonzini
object_property_set_bool(Object * obj,const char * name,bool value,Error ** errp)15216fd5bef1SMarkus Armbruster bool object_property_set_bool(Object *obj, const char *name,
15225325cc34SMarkus Armbruster bool value, Error **errp)
15237b7b7d18SPaolo Bonzini {
1524fc48ffc3SEric Blake QBool *qbool = qbool_from_bool(value);
15256fd5bef1SMarkus Armbruster bool ok = object_property_set_qobject(obj, name, QOBJECT(qbool), errp);
15267b7b7d18SPaolo Bonzini
1527cb3e7f08SMarc-André Lureau qobject_unref(qbool);
15286fd5bef1SMarkus Armbruster return ok;
15297b7b7d18SPaolo Bonzini }
15307b7b7d18SPaolo Bonzini
object_property_get_bool(Object * obj,const char * name,Error ** errp)15317b7b7d18SPaolo Bonzini bool object_property_get_bool(Object *obj, const char *name,
15327b7b7d18SPaolo Bonzini Error **errp)
15337b7b7d18SPaolo Bonzini {
15347b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp);
15357b7b7d18SPaolo Bonzini QBool *qbool;
15367b7b7d18SPaolo Bonzini bool retval;
15377b7b7d18SPaolo Bonzini
15387b7b7d18SPaolo Bonzini if (!ret) {
15397b7b7d18SPaolo Bonzini return false;
15407b7b7d18SPaolo Bonzini }
15417dc847ebSMax Reitz qbool = qobject_to(QBool, ret);
15427b7b7d18SPaolo Bonzini if (!qbool) {
1543aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: boolean",
1544aaeafa50SPhilippe Mathieu-Daudé name);
15457b7b7d18SPaolo Bonzini retval = false;
15467b7b7d18SPaolo Bonzini } else {
1547fc48ffc3SEric Blake retval = qbool_get_bool(qbool);
15487b7b7d18SPaolo Bonzini }
15497b7b7d18SPaolo Bonzini
1550cb3e7f08SMarc-André Lureau qobject_unref(ret);
15517b7b7d18SPaolo Bonzini return retval;
15527b7b7d18SPaolo Bonzini }
15537b7b7d18SPaolo Bonzini
object_property_set_int(Object * obj,const char * name,int64_t value,Error ** errp)15546fd5bef1SMarkus Armbruster bool object_property_set_int(Object *obj, const char *name,
15555325cc34SMarkus Armbruster int64_t value, Error **errp)
15567b7b7d18SPaolo Bonzini {
155701b2ffceSMarc-André Lureau QNum *qnum = qnum_from_int(value);
15586fd5bef1SMarkus Armbruster bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
15597b7b7d18SPaolo Bonzini
1560cb3e7f08SMarc-André Lureau qobject_unref(qnum);
15616fd5bef1SMarkus Armbruster return ok;
15627b7b7d18SPaolo Bonzini }
15637b7b7d18SPaolo Bonzini
object_property_get_int(Object * obj,const char * name,Error ** errp)15647b7b7d18SPaolo Bonzini int64_t object_property_get_int(Object *obj, const char *name,
15657b7b7d18SPaolo Bonzini Error **errp)
15667b7b7d18SPaolo Bonzini {
15677b7b7d18SPaolo Bonzini QObject *ret = object_property_get_qobject(obj, name, errp);
156801b2ffceSMarc-André Lureau QNum *qnum;
15697b7b7d18SPaolo Bonzini int64_t retval;
15707b7b7d18SPaolo Bonzini
15717b7b7d18SPaolo Bonzini if (!ret) {
15727b7b7d18SPaolo Bonzini return -1;
15737b7b7d18SPaolo Bonzini }
157401b2ffceSMarc-André Lureau
15757dc847ebSMax Reitz qnum = qobject_to(QNum, ret);
157601b2ffceSMarc-André Lureau if (!qnum || !qnum_get_try_int(qnum, &retval)) {
1577aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: int",
1578aaeafa50SPhilippe Mathieu-Daudé name);
15797b7b7d18SPaolo Bonzini retval = -1;
15807b7b7d18SPaolo Bonzini }
15817b7b7d18SPaolo Bonzini
1582cb3e7f08SMarc-André Lureau qobject_unref(ret);
15837b7b7d18SPaolo Bonzini return retval;
15847b7b7d18SPaolo Bonzini }
15857b7b7d18SPaolo Bonzini
object_property_init_defval(Object * obj,ObjectProperty * prop)15860e76ed0aSMarc-André Lureau static void object_property_init_defval(Object *obj, ObjectProperty *prop)
15870e76ed0aSMarc-André Lureau {
15880e76ed0aSMarc-André Lureau Visitor *v = qobject_input_visitor_new(prop->defval);
15890e76ed0aSMarc-André Lureau
15900e76ed0aSMarc-André Lureau assert(prop->set != NULL);
15910e76ed0aSMarc-André Lureau prop->set(obj, v, prop->name, prop->opaque, &error_abort);
15920e76ed0aSMarc-André Lureau
15930e76ed0aSMarc-André Lureau visit_free(v);
15940e76ed0aSMarc-André Lureau }
15950e76ed0aSMarc-André Lureau
object_property_set_default(ObjectProperty * prop,QObject * defval)15960e76ed0aSMarc-André Lureau static void object_property_set_default(ObjectProperty *prop, QObject *defval)
15970e76ed0aSMarc-André Lureau {
15980e76ed0aSMarc-André Lureau assert(!prop->defval);
15990e76ed0aSMarc-André Lureau assert(!prop->init);
16000e76ed0aSMarc-André Lureau
16010e76ed0aSMarc-André Lureau prop->defval = defval;
16020e76ed0aSMarc-André Lureau prop->init = object_property_init_defval;
16030e76ed0aSMarc-André Lureau }
16040e76ed0aSMarc-André Lureau
object_property_set_default_bool(ObjectProperty * prop,bool value)16050e76ed0aSMarc-André Lureau void object_property_set_default_bool(ObjectProperty *prop, bool value)
16060e76ed0aSMarc-André Lureau {
16070e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qbool_from_bool(value)));
16080e76ed0aSMarc-André Lureau }
16090e76ed0aSMarc-André Lureau
object_property_set_default_str(ObjectProperty * prop,const char * value)16100e76ed0aSMarc-André Lureau void object_property_set_default_str(ObjectProperty *prop, const char *value)
16110e76ed0aSMarc-André Lureau {
16120e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qstring_from_str(value)));
16130e76ed0aSMarc-André Lureau }
16140e76ed0aSMarc-André Lureau
object_property_set_default_list(ObjectProperty * prop)1615125062e7SKevin Wolf void object_property_set_default_list(ObjectProperty *prop)
1616125062e7SKevin Wolf {
1617125062e7SKevin Wolf object_property_set_default(prop, QOBJECT(qlist_new()));
1618125062e7SKevin Wolf }
1619125062e7SKevin Wolf
object_property_set_default_int(ObjectProperty * prop,int64_t value)16200e76ed0aSMarc-André Lureau void object_property_set_default_int(ObjectProperty *prop, int64_t value)
16210e76ed0aSMarc-André Lureau {
16220e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qnum_from_int(value)));
16230e76ed0aSMarc-André Lureau }
16240e76ed0aSMarc-André Lureau
object_property_set_default_uint(ObjectProperty * prop,uint64_t value)16250e76ed0aSMarc-André Lureau void object_property_set_default_uint(ObjectProperty *prop, uint64_t value)
16260e76ed0aSMarc-André Lureau {
16270e76ed0aSMarc-André Lureau object_property_set_default(prop, QOBJECT(qnum_from_uint(value)));
16280e76ed0aSMarc-André Lureau }
16290e76ed0aSMarc-André Lureau
object_property_set_uint(Object * obj,const char * name,uint64_t value,Error ** errp)16306fd5bef1SMarkus Armbruster bool object_property_set_uint(Object *obj, const char *name,
16315325cc34SMarkus Armbruster uint64_t value, Error **errp)
16323152779cSMarc-André Lureau {
16333152779cSMarc-André Lureau QNum *qnum = qnum_from_uint(value);
16346fd5bef1SMarkus Armbruster bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
16353152779cSMarc-André Lureau
1636cb3e7f08SMarc-André Lureau qobject_unref(qnum);
16376fd5bef1SMarkus Armbruster return ok;
16383152779cSMarc-André Lureau }
16393152779cSMarc-André Lureau
object_property_get_uint(Object * obj,const char * name,Error ** errp)16403152779cSMarc-André Lureau uint64_t object_property_get_uint(Object *obj, const char *name,
16413152779cSMarc-André Lureau Error **errp)
16423152779cSMarc-André Lureau {
16433152779cSMarc-André Lureau QObject *ret = object_property_get_qobject(obj, name, errp);
16443152779cSMarc-André Lureau QNum *qnum;
16453152779cSMarc-André Lureau uint64_t retval;
16463152779cSMarc-André Lureau
16473152779cSMarc-André Lureau if (!ret) {
16483152779cSMarc-André Lureau return 0;
16493152779cSMarc-André Lureau }
16507dc847ebSMax Reitz qnum = qobject_to(QNum, ret);
16513152779cSMarc-André Lureau if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
1652aaeafa50SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: uint",
1653aaeafa50SPhilippe Mathieu-Daudé name);
16543152779cSMarc-André Lureau retval = 0;
16553152779cSMarc-André Lureau }
16563152779cSMarc-André Lureau
1657cb3e7f08SMarc-André Lureau qobject_unref(ret);
16583152779cSMarc-André Lureau return retval;
16593152779cSMarc-André Lureau }
16603152779cSMarc-André Lureau
1661a8e3fbedSDaniel P. Berrange typedef struct EnumProperty {
1662f7abe0ecSMarc-André Lureau const QEnumLookup *lookup;
1663a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **);
1664a8e3fbedSDaniel P. Berrange void (*set)(Object *, int, Error **);
1665a8e3fbedSDaniel P. Berrange } EnumProperty;
1666a8e3fbedSDaniel P. Berrange
object_property_get_enum(Object * obj,const char * name,const char * typename,Error ** errp)16671f21772dSHu Tao int object_property_get_enum(Object *obj, const char *name,
1668a3590dacSDaniel P. Berrange const char *typename, Error **errp)
16691f21772dSHu Tao {
1670976620acSChen Fan char *str;
16711f21772dSHu Tao int ret;
1672efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find_err(obj, name, errp);
1673a3590dacSDaniel P. Berrange EnumProperty *enumprop;
1674a3590dacSDaniel P. Berrange
1675a3590dacSDaniel P. Berrange if (prop == NULL) {
1676d20f616eSMarkus Armbruster return -1;
1677a3590dacSDaniel P. Berrange }
1678a3590dacSDaniel P. Berrange
1679a3590dacSDaniel P. Berrange if (!g_str_equal(prop->type, typename)) {
1680a3590dacSDaniel P. Berrange error_setg(errp, "Property %s on %s is not '%s' enum type",
1681a3590dacSDaniel P. Berrange name, object_class_get_name(
1682a3590dacSDaniel P. Berrange object_get_class(obj)), typename);
1683d20f616eSMarkus Armbruster return -1;
1684a3590dacSDaniel P. Berrange }
1685a3590dacSDaniel P. Berrange
1686a3590dacSDaniel P. Berrange enumprop = prop->opaque;
16871f21772dSHu Tao
1688b555f89fSMarkus Armbruster str = object_property_get_str(obj, name, errp);
1689b555f89fSMarkus Armbruster if (!str) {
1690d20f616eSMarkus Armbruster return -1;
16914715d42eSMarkus Armbruster }
1692976620acSChen Fan
1693ea097dffSMarkus Armbruster ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
1694976620acSChen Fan g_free(str);
16951f21772dSHu Tao
16961f21772dSHu Tao return ret;
16971f21772dSHu Tao }
16981f21772dSHu Tao
object_property_parse(Object * obj,const char * name,const char * string,Error ** errp)16996fd5bef1SMarkus Armbruster bool object_property_parse(Object *obj, const char *name,
17005325cc34SMarkus Armbruster const char *string, Error **errp)
1701b2cd7deeSPaolo Bonzini {
17027a0525c7SEric Blake Visitor *v = string_input_visitor_new(string);
17036fd5bef1SMarkus Armbruster bool ok = object_property_set(obj, name, v, errp);
17046fd5bef1SMarkus Armbruster
17057a0525c7SEric Blake visit_free(v);
17066fd5bef1SMarkus Armbruster return ok;
1707b2cd7deeSPaolo Bonzini }
1708b2cd7deeSPaolo Bonzini
object_property_print(Object * obj,const char * name,bool human,Error ** errp)17090b7593e0SPaolo Bonzini char *object_property_print(Object *obj, const char *name, bool human,
1710b2cd7deeSPaolo Bonzini Error **errp)
1711b2cd7deeSPaolo Bonzini {
17123b098d56SEric Blake Visitor *v;
17133a53009fSGonglei char *string = NULL;
1714b2cd7deeSPaolo Bonzini
17153b098d56SEric Blake v = string_output_visitor_new(human, &string);
1716af175e85SMarkus Armbruster if (!object_property_get(obj, name, v, errp)) {
17173a53009fSGonglei goto out;
17183a53009fSGonglei }
17193a53009fSGonglei
17203b098d56SEric Blake visit_complete(v, &string);
17213a53009fSGonglei
17223a53009fSGonglei out:
17233b098d56SEric Blake visit_free(v);
1724b2cd7deeSPaolo Bonzini return string;
1725b2cd7deeSPaolo Bonzini }
1726b2cd7deeSPaolo Bonzini
object_property_get_type(Object * obj,const char * name,Error ** errp)172757c9fafeSAnthony Liguori const char *object_property_get_type(Object *obj, const char *name, Error **errp)
172857c9fafeSAnthony Liguori {
1729efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find_err(obj, name, errp);
173057c9fafeSAnthony Liguori if (prop == NULL) {
173157c9fafeSAnthony Liguori return NULL;
173257c9fafeSAnthony Liguori }
173357c9fafeSAnthony Liguori
173457c9fafeSAnthony Liguori return prop->type;
173557c9fafeSAnthony Liguori }
173657c9fafeSAnthony Liguori
object_get_root(void)173757c9fafeSAnthony Liguori Object *object_get_root(void)
173857c9fafeSAnthony Liguori {
17398b45d447SAnthony Liguori static Object *root;
174057c9fafeSAnthony Liguori
17418b45d447SAnthony Liguori if (!root) {
17428b45d447SAnthony Liguori root = object_new("container");
174357c9fafeSAnthony Liguori }
174457c9fafeSAnthony Liguori
17458b45d447SAnthony Liguori return root;
174657c9fafeSAnthony Liguori }
174757c9fafeSAnthony Liguori
object_get_objects_root(void)1748bc2256c4SDaniel P. Berrange Object *object_get_objects_root(void)
1749bc2256c4SDaniel P. Berrange {
1750bc2256c4SDaniel P. Berrange return container_get(object_get_root(), "/objects");
1751bc2256c4SDaniel P. Berrange }
1752bc2256c4SDaniel P. Berrange
object_get_internal_root(void)17537c47c4eaSPeter Xu Object *object_get_internal_root(void)
17547c47c4eaSPeter Xu {
17557c47c4eaSPeter Xu static Object *internal_root;
17567c47c4eaSPeter Xu
17577c47c4eaSPeter Xu if (!internal_root) {
17587c47c4eaSPeter Xu internal_root = object_new("container");
17597c47c4eaSPeter Xu }
17607c47c4eaSPeter Xu
17617c47c4eaSPeter Xu return internal_root;
17627c47c4eaSPeter Xu }
17637c47c4eaSPeter Xu
object_get_child_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1764d7bce999SEric Blake static void object_get_child_property(Object *obj, Visitor *v,
1765d7bce999SEric Blake const char *name, void *opaque,
1766d7bce999SEric Blake Error **errp)
176757c9fafeSAnthony Liguori {
176857c9fafeSAnthony Liguori Object *child = opaque;
1769ddfb0baaSMarkus Armbruster char *path;
177057c9fafeSAnthony Liguori
177157c9fafeSAnthony Liguori path = object_get_canonical_path(child);
177251e72bc1SEric Blake visit_type_str(v, name, &path, errp);
177357c9fafeSAnthony Liguori g_free(path);
177457c9fafeSAnthony Liguori }
177557c9fafeSAnthony Liguori
object_resolve_child_property(Object * parent,void * opaque,const char * part)1776ddfb0baaSMarkus Armbruster static Object *object_resolve_child_property(Object *parent, void *opaque,
1777ddfb0baaSMarkus Armbruster const char *part)
177864607d08SPaolo Bonzini {
177964607d08SPaolo Bonzini return opaque;
178064607d08SPaolo Bonzini }
178164607d08SPaolo Bonzini
object_finalize_child_property(Object * obj,const char * name,void * opaque)1782db85b575SAnthony Liguori static void object_finalize_child_property(Object *obj, const char *name,
1783db85b575SAnthony Liguori void *opaque)
1784db85b575SAnthony Liguori {
1785db85b575SAnthony Liguori Object *child = opaque;
1786db85b575SAnthony Liguori
1787bffc687dSPaolo Bonzini if (child->class->unparent) {
1788bffc687dSPaolo Bonzini (child->class->unparent)(child);
1789bffc687dSPaolo Bonzini }
1790bffc687dSPaolo Bonzini child->parent = NULL;
1791db85b575SAnthony Liguori object_unref(child);
1792db85b575SAnthony Liguori }
1793db85b575SAnthony Liguori
179470251887SMarkus Armbruster ObjectProperty *
object_property_try_add_child(Object * obj,const char * name,Object * child,Error ** errp)1795db57fef1SEric Auger object_property_try_add_child(Object *obj, const char *name,
1796db57fef1SEric Auger Object *child, Error **errp)
179757c9fafeSAnthony Liguori {
179870251887SMarkus Armbruster g_autofree char *type = NULL;
179964607d08SPaolo Bonzini ObjectProperty *op;
180057c9fafeSAnthony Liguori
1801d2623129SMarkus Armbruster assert(!child->parent);
18028faa2f85SPeter Crosthwaite
1803688ffbb4SPhilippe Mathieu-Daudé type = g_strdup_printf("child<%s>", object_get_typename(child));
180457c9fafeSAnthony Liguori
1805db57fef1SEric Auger op = object_property_try_add(obj, name, type, object_get_child_property,
1806db57fef1SEric Auger NULL, object_finalize_child_property,
1807db57fef1SEric Auger child, errp);
1808db57fef1SEric Auger if (!op) {
1809db57fef1SEric Auger return NULL;
1810db57fef1SEric Auger }
181164607d08SPaolo Bonzini op->resolve = object_resolve_child_property;
181257c9fafeSAnthony Liguori object_ref(child);
181357c9fafeSAnthony Liguori child->parent = obj;
181470251887SMarkus Armbruster return op;
181557c9fafeSAnthony Liguori }
181657c9fafeSAnthony Liguori
1817db57fef1SEric Auger ObjectProperty *
object_property_add_child(Object * obj,const char * name,Object * child)1818db57fef1SEric Auger object_property_add_child(Object *obj, const char *name,
1819db57fef1SEric Auger Object *child)
1820db57fef1SEric Auger {
1821db57fef1SEric Auger return object_property_try_add_child(obj, name, child, &error_abort);
1822db57fef1SEric Auger }
1823db57fef1SEric Auger
object_property_allow_set_link(const Object * obj,const char * name,Object * val,Error ** errp)18248f5d58efSIgor Mammedov void object_property_allow_set_link(const Object *obj, const char *name,
182539f72ef9SStefan Hajnoczi Object *val, Error **errp)
182639f72ef9SStefan Hajnoczi {
182739f72ef9SStefan Hajnoczi /* Allow the link to be set, always */
182839f72ef9SStefan Hajnoczi }
182939f72ef9SStefan Hajnoczi
18309561fda8SStefan Hajnoczi typedef struct {
18319941d37bSMarc-André Lureau union {
183236854207SMarc-André Lureau Object **targetp;
18339941d37bSMarc-André Lureau Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer */
1834840ecdfbSMarc-André Lureau ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */
18359941d37bSMarc-André Lureau };
18368f5d58efSIgor Mammedov void (*check)(const Object *, const char *, Object *, Error **);
18379561fda8SStefan Hajnoczi ObjectPropertyLinkFlags flags;
18389561fda8SStefan Hajnoczi } LinkProperty;
18399561fda8SStefan Hajnoczi
18409941d37bSMarc-André Lureau static Object **
object_link_get_targetp(Object * obj,LinkProperty * lprop)18419941d37bSMarc-André Lureau object_link_get_targetp(Object *obj, LinkProperty *lprop)
18429941d37bSMarc-André Lureau {
18439941d37bSMarc-André Lureau if (lprop->flags & OBJ_PROP_LINK_DIRECT) {
18449941d37bSMarc-André Lureau return &lprop->target;
1845840ecdfbSMarc-André Lureau } else if (lprop->flags & OBJ_PROP_LINK_CLASS) {
1846840ecdfbSMarc-André Lureau return (void *)obj + lprop->offset;
18479941d37bSMarc-André Lureau } else {
18489941d37bSMarc-André Lureau return lprop->targetp;
18499941d37bSMarc-André Lureau }
18509941d37bSMarc-André Lureau }
18519941d37bSMarc-André Lureau
object_get_link_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1852d7bce999SEric Blake static void object_get_link_property(Object *obj, Visitor *v,
1853d7bce999SEric Blake const char *name, void *opaque,
1854d7bce999SEric Blake Error **errp)
185557c9fafeSAnthony Liguori {
18569561fda8SStefan Hajnoczi LinkProperty *lprop = opaque;
18579941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, lprop);
1858ddfb0baaSMarkus Armbruster char *path;
185957c9fafeSAnthony Liguori
186036854207SMarc-André Lureau if (*targetp) {
186136854207SMarc-André Lureau path = object_get_canonical_path(*targetp);
186251e72bc1SEric Blake visit_type_str(v, name, &path, errp);
186357c9fafeSAnthony Liguori g_free(path);
186457c9fafeSAnthony Liguori } else {
1865ddfb0baaSMarkus Armbruster path = (char *)"";
186651e72bc1SEric Blake visit_type_str(v, name, &path, errp);
186757c9fafeSAnthony Liguori }
186857c9fafeSAnthony Liguori }
186957c9fafeSAnthony Liguori
1870f5ec6704SStefan Hajnoczi /*
1871f5ec6704SStefan Hajnoczi * object_resolve_link:
1872f5ec6704SStefan Hajnoczi *
1873f5ec6704SStefan Hajnoczi * Lookup an object and ensure its type matches the link property type. This
1874f5ec6704SStefan Hajnoczi * is similar to object_resolve_path() except type verification against the
1875f5ec6704SStefan Hajnoczi * link property is performed.
1876f5ec6704SStefan Hajnoczi *
1877f5ec6704SStefan Hajnoczi * Returns: The matched object or NULL on path lookup failures.
1878f5ec6704SStefan Hajnoczi */
object_resolve_link(Object * obj,const char * name,const char * path,Error ** errp)1879f5ec6704SStefan Hajnoczi static Object *object_resolve_link(Object *obj, const char *name,
1880f5ec6704SStefan Hajnoczi const char *path, Error **errp)
1881f5ec6704SStefan Hajnoczi {
1882f5ec6704SStefan Hajnoczi const char *type;
1883ddfb0baaSMarkus Armbruster char *target_type;
1884f5ec6704SStefan Hajnoczi bool ambiguous = false;
1885f5ec6704SStefan Hajnoczi Object *target;
1886f5ec6704SStefan Hajnoczi
1887f5ec6704SStefan Hajnoczi /* Go from link<FOO> to FOO. */
1888f5ec6704SStefan Hajnoczi type = object_property_get_type(obj, name, NULL);
1889f5ec6704SStefan Hajnoczi target_type = g_strndup(&type[5], strlen(type) - 6);
1890f5ec6704SStefan Hajnoczi target = object_resolve_path_type(path, target_type, &ambiguous);
1891f5ec6704SStefan Hajnoczi
1892f5ec6704SStefan Hajnoczi if (ambiguous) {
1893455b0fdeSEric Blake error_setg(errp, "Path '%s' does not uniquely identify an object",
1894455b0fdeSEric Blake path);
1895f5ec6704SStefan Hajnoczi } else if (!target) {
1896f5ec6704SStefan Hajnoczi target = object_resolve_path(path, &ambiguous);
1897f5ec6704SStefan Hajnoczi if (target || ambiguous) {
1898ef929281SPhilippe Mathieu-Daudé error_setg(errp, "Invalid parameter type for '%s', expected: %s",
1899ef929281SPhilippe Mathieu-Daudé name, target_type);
1900f5ec6704SStefan Hajnoczi } else {
190175158ebbSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
190275158ebbSMarkus Armbruster "Device '%s' not found", path);
1903f5ec6704SStefan Hajnoczi }
1904f5ec6704SStefan Hajnoczi target = NULL;
1905f5ec6704SStefan Hajnoczi }
1906f5ec6704SStefan Hajnoczi g_free(target_type);
1907f5ec6704SStefan Hajnoczi
1908f5ec6704SStefan Hajnoczi return target;
1909f5ec6704SStefan Hajnoczi }
1910f5ec6704SStefan Hajnoczi
object_set_link_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1911d7bce999SEric Blake static void object_set_link_property(Object *obj, Visitor *v,
1912d7bce999SEric Blake const char *name, void *opaque,
1913d7bce999SEric Blake Error **errp)
191457c9fafeSAnthony Liguori {
1915c6aed983SStefan Hajnoczi Error *local_err = NULL;
19169561fda8SStefan Hajnoczi LinkProperty *prop = opaque;
19179941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, prop);
191836854207SMarc-André Lureau Object *old_target = *targetp;
19191c94a351SMarkus Armbruster Object *new_target;
1920c6aed983SStefan Hajnoczi char *path = NULL;
192157c9fafeSAnthony Liguori
19221c94a351SMarkus Armbruster if (!visit_type_str(v, name, &path, errp)) {
19231c94a351SMarkus Armbruster return;
19241c94a351SMarkus Armbruster }
192557c9fafeSAnthony Liguori
19261c94a351SMarkus Armbruster if (*path) {
19271c94a351SMarkus Armbruster new_target = object_resolve_link(obj, name, path, errp);
19281c94a351SMarkus Armbruster if (!new_target) {
19291c94a351SMarkus Armbruster g_free(path);
19301c94a351SMarkus Armbruster return;
19311c94a351SMarkus Armbruster }
19321c94a351SMarkus Armbruster } else {
19331c94a351SMarkus Armbruster new_target = NULL;
193411e35bfdSPaolo Bonzini }
193557c9fafeSAnthony Liguori
193657c9fafeSAnthony Liguori g_free(path);
1937f0cdc966SAlexander Barabash
193839f72ef9SStefan Hajnoczi prop->check(obj, name, new_target, &local_err);
193939f72ef9SStefan Hajnoczi if (local_err) {
194039f72ef9SStefan Hajnoczi error_propagate(errp, local_err);
194139f72ef9SStefan Hajnoczi return;
194239f72ef9SStefan Hajnoczi }
194339f72ef9SStefan Hajnoczi
194436854207SMarc-André Lureau *targetp = new_target;
19458770bafdSMarc-André Lureau if (prop->flags & OBJ_PROP_LINK_STRONG) {
1946265b578cSMarc-André Lureau object_ref(new_target);
1947f0cdc966SAlexander Barabash object_unref(old_target);
1948f0cdc966SAlexander Barabash }
1949265b578cSMarc-André Lureau }
195057c9fafeSAnthony Liguori
object_resolve_link_property(Object * parent,void * opaque,const char * part)1951ddfb0baaSMarkus Armbruster static Object *object_resolve_link_property(Object *parent, void *opaque,
1952ddfb0baaSMarkus Armbruster const char *part)
195364607d08SPaolo Bonzini {
195464607d08SPaolo Bonzini LinkProperty *lprop = opaque;
195564607d08SPaolo Bonzini
19569941d37bSMarc-André Lureau return *object_link_get_targetp(parent, lprop);
195764607d08SPaolo Bonzini }
195864607d08SPaolo Bonzini
object_release_link_property(Object * obj,const char * name,void * opaque)19599561fda8SStefan Hajnoczi static void object_release_link_property(Object *obj, const char *name,
19609561fda8SStefan Hajnoczi void *opaque)
19619561fda8SStefan Hajnoczi {
19629561fda8SStefan Hajnoczi LinkProperty *prop = opaque;
19639941d37bSMarc-André Lureau Object **targetp = object_link_get_targetp(obj, prop);
19649561fda8SStefan Hajnoczi
19659941d37bSMarc-André Lureau if ((prop->flags & OBJ_PROP_LINK_STRONG) && *targetp) {
19669941d37bSMarc-André Lureau object_unref(*targetp);
19679561fda8SStefan Hajnoczi }
1968840ecdfbSMarc-André Lureau if (!(prop->flags & OBJ_PROP_LINK_CLASS)) {
19699561fda8SStefan Hajnoczi g_free(prop);
19709561fda8SStefan Hajnoczi }
1971840ecdfbSMarc-André Lureau }
19729561fda8SStefan Hajnoczi
197370251887SMarkus Armbruster static ObjectProperty *
object_add_link_prop(Object * obj,const char * name,const char * type,void * ptr,void (* check)(const Object *,const char *,Object *,Error **),ObjectPropertyLinkFlags flags)197470251887SMarkus Armbruster object_add_link_prop(Object *obj, const char *name,
19754a8d5798SMarc-André Lureau const char *type, void *ptr,
19768f5d58efSIgor Mammedov void (*check)(const Object *, const char *,
197739f72ef9SStefan Hajnoczi Object *, Error **),
1978d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags)
197957c9fafeSAnthony Liguori {
19809561fda8SStefan Hajnoczi LinkProperty *prop = g_malloc(sizeof(*prop));
198170251887SMarkus Armbruster g_autofree char *full_type = NULL;
198264607d08SPaolo Bonzini ObjectProperty *op;
198357c9fafeSAnthony Liguori
19844a8d5798SMarc-André Lureau if (flags & OBJ_PROP_LINK_DIRECT) {
19854a8d5798SMarc-André Lureau prop->target = ptr;
19864a8d5798SMarc-André Lureau } else {
19874a8d5798SMarc-André Lureau prop->targetp = ptr;
19884a8d5798SMarc-André Lureau }
198939f72ef9SStefan Hajnoczi prop->check = check;
19909561fda8SStefan Hajnoczi prop->flags = flags;
19919561fda8SStefan Hajnoczi
199257c9fafeSAnthony Liguori full_type = g_strdup_printf("link<%s>", type);
199357c9fafeSAnthony Liguori
199464607d08SPaolo Bonzini op = object_property_add(obj, name, full_type,
199557c9fafeSAnthony Liguori object_get_link_property,
199639f72ef9SStefan Hajnoczi check ? object_set_link_property : NULL,
19979561fda8SStefan Hajnoczi object_release_link_property,
1998d2623129SMarkus Armbruster prop);
199964607d08SPaolo Bonzini op->resolve = object_resolve_link_property;
200070251887SMarkus Armbruster return op;
200157c9fafeSAnthony Liguori }
200257c9fafeSAnthony Liguori
200370251887SMarkus Armbruster ObjectProperty *
object_property_add_link(Object * obj,const char * name,const char * type,Object ** targetp,void (* check)(const Object *,const char *,Object *,Error **),ObjectPropertyLinkFlags flags)200470251887SMarkus Armbruster object_property_add_link(Object *obj, const char *name,
20054a8d5798SMarc-André Lureau const char *type, Object **targetp,
20064a8d5798SMarc-André Lureau void (*check)(const Object *, const char *,
20074a8d5798SMarc-André Lureau Object *, Error **),
2008d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags)
20094a8d5798SMarc-André Lureau {
2010d2623129SMarkus Armbruster return object_add_link_prop(obj, name, type, targetp, check, flags);
20114a8d5798SMarc-André Lureau }
20124a8d5798SMarc-André Lureau
2013840ecdfbSMarc-André Lureau ObjectProperty *
object_class_property_add_link(ObjectClass * oc,const char * name,const char * type,ptrdiff_t offset,void (* check)(const Object * obj,const char * name,Object * val,Error ** errp),ObjectPropertyLinkFlags flags)2014840ecdfbSMarc-André Lureau object_class_property_add_link(ObjectClass *oc,
2015840ecdfbSMarc-André Lureau const char *name,
2016840ecdfbSMarc-André Lureau const char *type, ptrdiff_t offset,
2017840ecdfbSMarc-André Lureau void (*check)(const Object *obj, const char *name,
2018840ecdfbSMarc-André Lureau Object *val, Error **errp),
2019d2623129SMarkus Armbruster ObjectPropertyLinkFlags flags)
2020840ecdfbSMarc-André Lureau {
2021840ecdfbSMarc-André Lureau LinkProperty *prop = g_new0(LinkProperty, 1);
2022ddfb0baaSMarkus Armbruster char *full_type;
2023840ecdfbSMarc-André Lureau ObjectProperty *op;
2024840ecdfbSMarc-André Lureau
2025840ecdfbSMarc-André Lureau prop->offset = offset;
2026840ecdfbSMarc-André Lureau prop->check = check;
2027840ecdfbSMarc-André Lureau prop->flags = flags | OBJ_PROP_LINK_CLASS;
2028840ecdfbSMarc-André Lureau
2029840ecdfbSMarc-André Lureau full_type = g_strdup_printf("link<%s>", type);
2030840ecdfbSMarc-André Lureau
2031840ecdfbSMarc-André Lureau op = object_class_property_add(oc, name, full_type,
2032840ecdfbSMarc-André Lureau object_get_link_property,
2033840ecdfbSMarc-André Lureau check ? object_set_link_property : NULL,
2034840ecdfbSMarc-André Lureau object_release_link_property,
2035d2623129SMarkus Armbruster prop);
2036840ecdfbSMarc-André Lureau
2037840ecdfbSMarc-André Lureau op->resolve = object_resolve_link_property;
2038840ecdfbSMarc-André Lureau
2039840ecdfbSMarc-André Lureau g_free(full_type);
2040840ecdfbSMarc-André Lureau return op;
2041840ecdfbSMarc-André Lureau }
2042840ecdfbSMarc-André Lureau
204370251887SMarkus Armbruster ObjectProperty *
object_property_add_const_link(Object * obj,const char * name,Object * target)204470251887SMarkus Armbruster object_property_add_const_link(Object *obj, const char *name,
2045d2623129SMarkus Armbruster Object *target)
2046fb9e7e33SPaolo Bonzini {
204770251887SMarkus Armbruster return object_add_link_prop(obj, name,
204870251887SMarkus Armbruster object_get_typename(target), target,
2049d2623129SMarkus Armbruster NULL, OBJ_PROP_LINK_DIRECT);
2050fb9e7e33SPaolo Bonzini }
2051fb9e7e33SPaolo Bonzini
object_get_canonical_path_component(const Object * obj)20527a309cc9SMarkus Armbruster const char *object_get_canonical_path_component(const Object *obj)
205357c9fafeSAnthony Liguori {
205457c9fafeSAnthony Liguori ObjectProperty *prop = NULL;
2055b604a854SPavel Fedin GHashTableIter iter;
205657c9fafeSAnthony Liguori
2057770dec26SPaolo Bonzini if (obj->parent == NULL) {
2058770dec26SPaolo Bonzini return NULL;
2059770dec26SPaolo Bonzini }
206057c9fafeSAnthony Liguori
2061b604a854SPavel Fedin g_hash_table_iter_init(&iter, obj->parent->properties);
2062b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
20635d9d3f47SAndreas Färber if (!object_property_is_child(prop)) {
206457c9fafeSAnthony Liguori continue;
206557c9fafeSAnthony Liguori }
206657c9fafeSAnthony Liguori
206757c9fafeSAnthony Liguori if (prop->opaque == obj) {
20687a309cc9SMarkus Armbruster return prop->name;
206957c9fafeSAnthony Liguori }
207057c9fafeSAnthony Liguori }
207157c9fafeSAnthony Liguori
207211f590b1SStefan Hajnoczi /* obj had a parent but was not a child, should never happen */
207311f590b1SStefan Hajnoczi g_assert_not_reached();
207411f590b1SStefan Hajnoczi }
207511f590b1SStefan Hajnoczi
object_get_canonical_path(const Object * obj)2076e8512dfaSMarkus Armbruster char *object_get_canonical_path(const Object *obj)
207711f590b1SStefan Hajnoczi {
207811f590b1SStefan Hajnoczi Object *root = object_get_root();
207911f590b1SStefan Hajnoczi char *newpath, *path = NULL;
208011f590b1SStefan Hajnoczi
2081e40077fdSPaolo Bonzini if (obj == root) {
2082e40077fdSPaolo Bonzini return g_strdup("/");
2083e40077fdSPaolo Bonzini }
2084e40077fdSPaolo Bonzini
2085e40077fdSPaolo Bonzini do {
20867a309cc9SMarkus Armbruster const char *component = object_get_canonical_path_component(obj);
208711f590b1SStefan Hajnoczi
2088e40077fdSPaolo Bonzini if (!component) {
2089e40077fdSPaolo Bonzini /* A canonical path must be complete, so discard what was
2090e40077fdSPaolo Bonzini * collected so far.
2091e40077fdSPaolo Bonzini */
2092e40077fdSPaolo Bonzini g_free(path);
2093e40077fdSPaolo Bonzini return NULL;
2094e40077fdSPaolo Bonzini }
2095e40077fdSPaolo Bonzini
2096e40077fdSPaolo Bonzini newpath = g_strdup_printf("/%s%s", component, path ? path : "");
2097e40077fdSPaolo Bonzini g_free(path);
209811f590b1SStefan Hajnoczi path = newpath;
209957c9fafeSAnthony Liguori obj = obj->parent;
2100e40077fdSPaolo Bonzini } while (obj != root);
210157c9fafeSAnthony Liguori
2102e40077fdSPaolo Bonzini return path;
210357c9fafeSAnthony Liguori }
210457c9fafeSAnthony Liguori
object_resolve_path_component(Object * parent,const char * part)2105ddfb0baaSMarkus Armbruster Object *object_resolve_path_component(Object *parent, const char *part)
2106a612b2a6SPaolo Bonzini {
2107efba1595SDaniel P. Berrangé ObjectProperty *prop = object_property_find(parent, part);
2108a612b2a6SPaolo Bonzini if (prop == NULL) {
2109a612b2a6SPaolo Bonzini return NULL;
2110a612b2a6SPaolo Bonzini }
2111a612b2a6SPaolo Bonzini
211264607d08SPaolo Bonzini if (prop->resolve) {
211364607d08SPaolo Bonzini return prop->resolve(parent, prop->opaque, part);
2114a612b2a6SPaolo Bonzini } else {
2115a612b2a6SPaolo Bonzini return NULL;
2116a612b2a6SPaolo Bonzini }
2117a612b2a6SPaolo Bonzini }
2118a612b2a6SPaolo Bonzini
object_resolve_abs_path(Object * parent,char ** parts,const char * typename)211957c9fafeSAnthony Liguori static Object *object_resolve_abs_path(Object *parent,
2120ddfb0baaSMarkus Armbruster char **parts,
2121ad195c8fSMasahiro Yamada const char *typename)
212257c9fafeSAnthony Liguori {
212357c9fafeSAnthony Liguori Object *child;
212457c9fafeSAnthony Liguori
2125ad195c8fSMasahiro Yamada if (*parts == NULL) {
212602fe2db6SPaolo Bonzini return object_dynamic_cast(parent, typename);
212757c9fafeSAnthony Liguori }
212857c9fafeSAnthony Liguori
2129ad195c8fSMasahiro Yamada if (strcmp(*parts, "") == 0) {
2130ad195c8fSMasahiro Yamada return object_resolve_abs_path(parent, parts + 1, typename);
213157c9fafeSAnthony Liguori }
213257c9fafeSAnthony Liguori
2133ad195c8fSMasahiro Yamada child = object_resolve_path_component(parent, *parts);
213457c9fafeSAnthony Liguori if (!child) {
213557c9fafeSAnthony Liguori return NULL;
213657c9fafeSAnthony Liguori }
213757c9fafeSAnthony Liguori
2138ad195c8fSMasahiro Yamada return object_resolve_abs_path(child, parts + 1, typename);
213957c9fafeSAnthony Liguori }
214057c9fafeSAnthony Liguori
object_resolve_partial_path(Object * parent,char ** parts,const char * typename,bool * ambiguous)214157c9fafeSAnthony Liguori static Object *object_resolve_partial_path(Object *parent,
2142ddfb0baaSMarkus Armbruster char **parts,
214302fe2db6SPaolo Bonzini const char *typename,
214457c9fafeSAnthony Liguori bool *ambiguous)
214557c9fafeSAnthony Liguori {
214657c9fafeSAnthony Liguori Object *obj;
2147b604a854SPavel Fedin GHashTableIter iter;
214857c9fafeSAnthony Liguori ObjectProperty *prop;
214957c9fafeSAnthony Liguori
2150ad195c8fSMasahiro Yamada obj = object_resolve_abs_path(parent, parts, typename);
215157c9fafeSAnthony Liguori
2152b604a854SPavel Fedin g_hash_table_iter_init(&iter, parent->properties);
2153b604a854SPavel Fedin while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
215457c9fafeSAnthony Liguori Object *found;
215557c9fafeSAnthony Liguori
21565d9d3f47SAndreas Färber if (!object_property_is_child(prop)) {
215757c9fafeSAnthony Liguori continue;
215857c9fafeSAnthony Liguori }
215957c9fafeSAnthony Liguori
216002fe2db6SPaolo Bonzini found = object_resolve_partial_path(prop->opaque, parts,
216102fe2db6SPaolo Bonzini typename, ambiguous);
216257c9fafeSAnthony Liguori if (found) {
216357c9fafeSAnthony Liguori if (obj) {
216457c9fafeSAnthony Liguori *ambiguous = true;
216557c9fafeSAnthony Liguori return NULL;
216657c9fafeSAnthony Liguori }
216757c9fafeSAnthony Liguori obj = found;
216857c9fafeSAnthony Liguori }
216957c9fafeSAnthony Liguori
2170ebcc479eSEduardo Habkost if (*ambiguous) {
217157c9fafeSAnthony Liguori return NULL;
217257c9fafeSAnthony Liguori }
217357c9fafeSAnthony Liguori }
217457c9fafeSAnthony Liguori
217557c9fafeSAnthony Liguori return obj;
217657c9fafeSAnthony Liguori }
217757c9fafeSAnthony Liguori
object_resolve_path_type(const char * path,const char * typename,bool * ambiguous)217802fe2db6SPaolo Bonzini Object *object_resolve_path_type(const char *path, const char *typename,
2179ee510704SMarc-André Lureau bool *ambiguous)
218057c9fafeSAnthony Liguori {
218157c9fafeSAnthony Liguori Object *obj;
2182ddfb0baaSMarkus Armbruster char **parts;
218357c9fafeSAnthony Liguori
218457c9fafeSAnthony Liguori parts = g_strsplit(path, "/", 0);
21852e1103f6SPaolo Bonzini assert(parts);
218657c9fafeSAnthony Liguori
21872e1103f6SPaolo Bonzini if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
2188ee510704SMarc-André Lureau bool ambig = false;
218902fe2db6SPaolo Bonzini obj = object_resolve_partial_path(object_get_root(), parts,
2190ee510704SMarc-André Lureau typename, &ambig);
2191ee510704SMarc-André Lureau if (ambiguous) {
2192ee510704SMarc-André Lureau *ambiguous = ambig;
2193ebcc479eSEduardo Habkost }
219457c9fafeSAnthony Liguori } else {
2195ad195c8fSMasahiro Yamada obj = object_resolve_abs_path(object_get_root(), parts + 1, typename);
2196d9e98673SMarc-André Lureau if (ambiguous) {
2197d9e98673SMarc-André Lureau *ambiguous = false;
2198d9e98673SMarc-André Lureau }
219957c9fafeSAnthony Liguori }
220057c9fafeSAnthony Liguori
220157c9fafeSAnthony Liguori g_strfreev(parts);
220257c9fafeSAnthony Liguori
220357c9fafeSAnthony Liguori return obj;
220457c9fafeSAnthony Liguori }
220557c9fafeSAnthony Liguori
object_resolve_path(const char * path,bool * ambiguous)220602fe2db6SPaolo Bonzini Object *object_resolve_path(const char *path, bool *ambiguous)
220702fe2db6SPaolo Bonzini {
220802fe2db6SPaolo Bonzini return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
220902fe2db6SPaolo Bonzini }
221002fe2db6SPaolo Bonzini
object_resolve_path_at(Object * parent,const char * path)22111bf4d329SMarkus Armbruster Object *object_resolve_path_at(Object *parent, const char *path)
22121bf4d329SMarkus Armbruster {
22131bf4d329SMarkus Armbruster g_auto(GStrv) parts = g_strsplit(path, "/", 0);
22141bf4d329SMarkus Armbruster
22151bf4d329SMarkus Armbruster if (*path == '/') {
22161bf4d329SMarkus Armbruster return object_resolve_abs_path(object_get_root(), parts + 1,
22171bf4d329SMarkus Armbruster TYPE_OBJECT);
22181bf4d329SMarkus Armbruster }
22191bf4d329SMarkus Armbruster return object_resolve_abs_path(parent, parts, TYPE_OBJECT);
22201bf4d329SMarkus Armbruster }
22211bf4d329SMarkus Armbruster
object_resolve_type_unambiguous(const char * typename,Error ** errp)2222ee3b34cdSPaolo Bonzini Object *object_resolve_type_unambiguous(const char *typename, Error **errp)
2223ee3b34cdSPaolo Bonzini {
22248f337543SMarc-André Lureau bool ambig = false;
2225ee3b34cdSPaolo Bonzini Object *o = object_resolve_path_type("", typename, &ambig);
2226ee3b34cdSPaolo Bonzini
2227ee3b34cdSPaolo Bonzini if (ambig) {
2228ee3b34cdSPaolo Bonzini error_setg(errp, "More than one object of type %s", typename);
2229ee3b34cdSPaolo Bonzini return NULL;
2230ee3b34cdSPaolo Bonzini }
2231ee3b34cdSPaolo Bonzini if (!o) {
2232ee3b34cdSPaolo Bonzini error_setg(errp, "No object found of type %s", typename);
2233ee3b34cdSPaolo Bonzini return NULL;
2234ee3b34cdSPaolo Bonzini }
2235ee3b34cdSPaolo Bonzini return o;
2236ee3b34cdSPaolo Bonzini }
2237ee3b34cdSPaolo Bonzini
223857c9fafeSAnthony Liguori typedef struct StringProperty
223957c9fafeSAnthony Liguori {
224057c9fafeSAnthony Liguori char *(*get)(Object *, Error **);
224157c9fafeSAnthony Liguori void (*set)(Object *, const char *, Error **);
224257c9fafeSAnthony Liguori } StringProperty;
224357c9fafeSAnthony Liguori
property_get_str(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2244d7bce999SEric Blake static void property_get_str(Object *obj, Visitor *v, const char *name,
2245d7bce999SEric Blake void *opaque, Error **errp)
224657c9fafeSAnthony Liguori {
224757c9fafeSAnthony Liguori StringProperty *prop = opaque;
224857c9fafeSAnthony Liguori char *value;
2249e1c8237dSMarkus Armbruster Error *err = NULL;
225057c9fafeSAnthony Liguori
2251e1c8237dSMarkus Armbruster value = prop->get(obj, &err);
2252e1c8237dSMarkus Armbruster if (err) {
2253e1c8237dSMarkus Armbruster error_propagate(errp, err);
2254e1c8237dSMarkus Armbruster return;
2255e1c8237dSMarkus Armbruster }
2256e1c8237dSMarkus Armbruster
225751e72bc1SEric Blake visit_type_str(v, name, &value, errp);
225857c9fafeSAnthony Liguori g_free(value);
225957c9fafeSAnthony Liguori }
226057c9fafeSAnthony Liguori
property_set_str(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2261d7bce999SEric Blake static void property_set_str(Object *obj, Visitor *v, const char *name,
2262d7bce999SEric Blake void *opaque, Error **errp)
226357c9fafeSAnthony Liguori {
226457c9fafeSAnthony Liguori StringProperty *prop = opaque;
226557c9fafeSAnthony Liguori char *value;
226657c9fafeSAnthony Liguori
2267668f62ecSMarkus Armbruster if (!visit_type_str(v, name, &value, errp)) {
226857c9fafeSAnthony Liguori return;
226957c9fafeSAnthony Liguori }
227057c9fafeSAnthony Liguori
227157c9fafeSAnthony Liguori prop->set(obj, value, errp);
227257c9fafeSAnthony Liguori g_free(value);
227357c9fafeSAnthony Liguori }
227457c9fafeSAnthony Liguori
property_release_data(Object * obj,const char * name,void * opaque)2275169cbac1SPaolo Bonzini static void property_release_data(Object *obj, const char *name,
227657c9fafeSAnthony Liguori void *opaque)
227757c9fafeSAnthony Liguori {
2278169cbac1SPaolo Bonzini g_free(opaque);
227957c9fafeSAnthony Liguori }
228057c9fafeSAnthony Liguori
228170251887SMarkus Armbruster ObjectProperty *
object_property_add_str(Object * obj,const char * name,char * (* get)(Object *,Error **),void (* set)(Object *,const char *,Error **))228270251887SMarkus Armbruster object_property_add_str(Object *obj, const char *name,
228357c9fafeSAnthony Liguori char *(*get)(Object *, Error **),
2284d2623129SMarkus Armbruster void (*set)(Object *, const char *, Error **))
228557c9fafeSAnthony Liguori {
228657c9fafeSAnthony Liguori StringProperty *prop = g_malloc0(sizeof(*prop));
228757c9fafeSAnthony Liguori
228857c9fafeSAnthony Liguori prop->get = get;
228957c9fafeSAnthony Liguori prop->set = set;
229057c9fafeSAnthony Liguori
2291d2623129SMarkus Armbruster return object_property_add(obj, name, "string",
22927b7b7d18SPaolo Bonzini get ? property_get_str : NULL,
22937b7b7d18SPaolo Bonzini set ? property_set_str : NULL,
2294169cbac1SPaolo Bonzini property_release_data,
2295d2623129SMarkus Armbruster prop);
229657c9fafeSAnthony Liguori }
2297745549c8SPaolo Bonzini
2298a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_str(ObjectClass * klass,const char * name,char * (* get)(Object *,Error **),void (* set)(Object *,const char *,Error **))2299a3a16211SMarc-André Lureau object_class_property_add_str(ObjectClass *klass, const char *name,
230016bf7f52SDaniel P. Berrange char *(*get)(Object *, Error **),
230116bf7f52SDaniel P. Berrange void (*set)(Object *, const char *,
2302d2623129SMarkus Armbruster Error **))
230316bf7f52SDaniel P. Berrange {
230416bf7f52SDaniel P. Berrange StringProperty *prop = g_malloc0(sizeof(*prop));
230516bf7f52SDaniel P. Berrange
230616bf7f52SDaniel P. Berrange prop->get = get;
230716bf7f52SDaniel P. Berrange prop->set = set;
230816bf7f52SDaniel P. Berrange
2309d2623129SMarkus Armbruster return object_class_property_add(klass, name, "string",
231016bf7f52SDaniel P. Berrange get ? property_get_str : NULL,
231116bf7f52SDaniel P. Berrange set ? property_set_str : NULL,
2312fc4fe712SMarc-André Lureau NULL,
2313d2623129SMarkus Armbruster prop);
231416bf7f52SDaniel P. Berrange }
231516bf7f52SDaniel P. Berrange
23160e558843SAnthony Liguori typedef struct BoolProperty
23170e558843SAnthony Liguori {
23180e558843SAnthony Liguori bool (*get)(Object *, Error **);
23190e558843SAnthony Liguori void (*set)(Object *, bool, Error **);
23200e558843SAnthony Liguori } BoolProperty;
23210e558843SAnthony Liguori
property_get_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2322d7bce999SEric Blake static void property_get_bool(Object *obj, Visitor *v, const char *name,
2323d7bce999SEric Blake void *opaque, Error **errp)
23240e558843SAnthony Liguori {
23250e558843SAnthony Liguori BoolProperty *prop = opaque;
23260e558843SAnthony Liguori bool value;
23274715d42eSMarkus Armbruster Error *err = NULL;
23280e558843SAnthony Liguori
23294715d42eSMarkus Armbruster value = prop->get(obj, &err);
23304715d42eSMarkus Armbruster if (err) {
23314715d42eSMarkus Armbruster error_propagate(errp, err);
23324715d42eSMarkus Armbruster return;
23334715d42eSMarkus Armbruster }
23344715d42eSMarkus Armbruster
233551e72bc1SEric Blake visit_type_bool(v, name, &value, errp);
23360e558843SAnthony Liguori }
23370e558843SAnthony Liguori
property_set_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2338d7bce999SEric Blake static void property_set_bool(Object *obj, Visitor *v, const char *name,
2339d7bce999SEric Blake void *opaque, Error **errp)
23400e558843SAnthony Liguori {
23410e558843SAnthony Liguori BoolProperty *prop = opaque;
23420e558843SAnthony Liguori bool value;
23430e558843SAnthony Liguori
2344668f62ecSMarkus Armbruster if (!visit_type_bool(v, name, &value, errp)) {
23450e558843SAnthony Liguori return;
23460e558843SAnthony Liguori }
23470e558843SAnthony Liguori
23480e558843SAnthony Liguori prop->set(obj, value, errp);
23490e558843SAnthony Liguori }
23500e558843SAnthony Liguori
235170251887SMarkus Armbruster ObjectProperty *
object_property_add_bool(Object * obj,const char * name,bool (* get)(Object *,Error **),void (* set)(Object *,bool,Error **))235270251887SMarkus Armbruster object_property_add_bool(Object *obj, const char *name,
23530e558843SAnthony Liguori bool (*get)(Object *, Error **),
2354d2623129SMarkus Armbruster void (*set)(Object *, bool, Error **))
23550e558843SAnthony Liguori {
23560e558843SAnthony Liguori BoolProperty *prop = g_malloc0(sizeof(*prop));
23570e558843SAnthony Liguori
23580e558843SAnthony Liguori prop->get = get;
23590e558843SAnthony Liguori prop->set = set;
23600e558843SAnthony Liguori
2361d2623129SMarkus Armbruster return object_property_add(obj, name, "bool",
23620e558843SAnthony Liguori get ? property_get_bool : NULL,
23630e558843SAnthony Liguori set ? property_set_bool : NULL,
2364169cbac1SPaolo Bonzini property_release_data,
2365d2623129SMarkus Armbruster prop);
23660e558843SAnthony Liguori }
23670e558843SAnthony Liguori
2368a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_bool(ObjectClass * klass,const char * name,bool (* get)(Object *,Error **),void (* set)(Object *,bool,Error **))2369a3a16211SMarc-André Lureau object_class_property_add_bool(ObjectClass *klass, const char *name,
237016bf7f52SDaniel P. Berrange bool (*get)(Object *, Error **),
2371d2623129SMarkus Armbruster void (*set)(Object *, bool, Error **))
237216bf7f52SDaniel P. Berrange {
237316bf7f52SDaniel P. Berrange BoolProperty *prop = g_malloc0(sizeof(*prop));
237416bf7f52SDaniel P. Berrange
237516bf7f52SDaniel P. Berrange prop->get = get;
237616bf7f52SDaniel P. Berrange prop->set = set;
237716bf7f52SDaniel P. Berrange
2378d2623129SMarkus Armbruster return object_class_property_add(klass, name, "bool",
237916bf7f52SDaniel P. Berrange get ? property_get_bool : NULL,
238016bf7f52SDaniel P. Berrange set ? property_set_bool : NULL,
2381fc4fe712SMarc-André Lureau NULL,
2382d2623129SMarkus Armbruster prop);
238316bf7f52SDaniel P. Berrange }
238416bf7f52SDaniel P. Berrange
property_get_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2385d7bce999SEric Blake static void property_get_enum(Object *obj, Visitor *v, const char *name,
2386d7bce999SEric Blake void *opaque, Error **errp)
2387a8e3fbedSDaniel P. Berrange {
2388a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque;
2389a8e3fbedSDaniel P. Berrange int value;
23904715d42eSMarkus Armbruster Error *err = NULL;
2391a8e3fbedSDaniel P. Berrange
23924715d42eSMarkus Armbruster value = prop->get(obj, &err);
23934715d42eSMarkus Armbruster if (err) {
23944715d42eSMarkus Armbruster error_propagate(errp, err);
23954715d42eSMarkus Armbruster return;
23964715d42eSMarkus Armbruster }
23974715d42eSMarkus Armbruster
2398f7abe0ecSMarc-André Lureau visit_type_enum(v, name, &value, prop->lookup, errp);
2399a8e3fbedSDaniel P. Berrange }
2400a8e3fbedSDaniel P. Berrange
property_set_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2401d7bce999SEric Blake static void property_set_enum(Object *obj, Visitor *v, const char *name,
2402d7bce999SEric Blake void *opaque, Error **errp)
2403a8e3fbedSDaniel P. Berrange {
2404a8e3fbedSDaniel P. Berrange EnumProperty *prop = opaque;
2405a8e3fbedSDaniel P. Berrange int value;
2406a8e3fbedSDaniel P. Berrange
2407668f62ecSMarkus Armbruster if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
24084715d42eSMarkus Armbruster return;
24094715d42eSMarkus Armbruster }
2410a8e3fbedSDaniel P. Berrange prop->set(obj, value, errp);
2411a8e3fbedSDaniel P. Berrange }
2412a8e3fbedSDaniel P. Berrange
241370251887SMarkus Armbruster ObjectProperty *
object_property_add_enum(Object * obj,const char * name,const char * typename,const QEnumLookup * lookup,int (* get)(Object *,Error **),void (* set)(Object *,int,Error **))241470251887SMarkus Armbruster object_property_add_enum(Object *obj, const char *name,
2415a8e3fbedSDaniel P. Berrange const char *typename,
2416f7abe0ecSMarc-André Lureau const QEnumLookup *lookup,
2417a8e3fbedSDaniel P. Berrange int (*get)(Object *, Error **),
2418d2623129SMarkus Armbruster void (*set)(Object *, int, Error **))
2419a8e3fbedSDaniel P. Berrange {
2420a8e3fbedSDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop));
2421a8e3fbedSDaniel P. Berrange
2422f7abe0ecSMarc-André Lureau prop->lookup = lookup;
2423a8e3fbedSDaniel P. Berrange prop->get = get;
2424a8e3fbedSDaniel P. Berrange prop->set = set;
2425a8e3fbedSDaniel P. Berrange
2426d2623129SMarkus Armbruster return object_property_add(obj, name, typename,
2427a8e3fbedSDaniel P. Berrange get ? property_get_enum : NULL,
2428a8e3fbedSDaniel P. Berrange set ? property_set_enum : NULL,
2429169cbac1SPaolo Bonzini property_release_data,
2430d2623129SMarkus Armbruster prop);
2431a8e3fbedSDaniel P. Berrange }
2432a8e3fbedSDaniel P. Berrange
2433a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_enum(ObjectClass * klass,const char * name,const char * typename,const QEnumLookup * lookup,int (* get)(Object *,Error **),void (* set)(Object *,int,Error **))2434a3a16211SMarc-André Lureau object_class_property_add_enum(ObjectClass *klass, const char *name,
243516bf7f52SDaniel P. Berrange const char *typename,
2436f7abe0ecSMarc-André Lureau const QEnumLookup *lookup,
243716bf7f52SDaniel P. Berrange int (*get)(Object *, Error **),
2438d2623129SMarkus Armbruster void (*set)(Object *, int, Error **))
243916bf7f52SDaniel P. Berrange {
244016bf7f52SDaniel P. Berrange EnumProperty *prop = g_malloc(sizeof(*prop));
244116bf7f52SDaniel P. Berrange
2442f7abe0ecSMarc-André Lureau prop->lookup = lookup;
244316bf7f52SDaniel P. Berrange prop->get = get;
244416bf7f52SDaniel P. Berrange prop->set = set;
244516bf7f52SDaniel P. Berrange
2446d2623129SMarkus Armbruster return object_class_property_add(klass, name, typename,
244716bf7f52SDaniel P. Berrange get ? property_get_enum : NULL,
244816bf7f52SDaniel P. Berrange set ? property_set_enum : NULL,
2449fc4fe712SMarc-André Lureau NULL,
2450d2623129SMarkus Armbruster prop);
245116bf7f52SDaniel P. Berrange }
245216bf7f52SDaniel P. Berrange
24538e099d14SDavid Gibson typedef struct TMProperty {
24548e099d14SDavid Gibson void (*get)(Object *, struct tm *, Error **);
24558e099d14SDavid Gibson } TMProperty;
24568e099d14SDavid Gibson
property_get_tm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2457d7bce999SEric Blake static void property_get_tm(Object *obj, Visitor *v, const char *name,
2458d7bce999SEric Blake void *opaque, Error **errp)
24598e099d14SDavid Gibson {
24608e099d14SDavid Gibson TMProperty *prop = opaque;
24618e099d14SDavid Gibson Error *err = NULL;
24628e099d14SDavid Gibson struct tm value;
24638e099d14SDavid Gibson
24648e099d14SDavid Gibson prop->get(obj, &value, &err);
24658e099d14SDavid Gibson if (err) {
2466992861fbSMarkus Armbruster error_propagate(errp, err);
2467992861fbSMarkus Armbruster return;
24688e099d14SDavid Gibson }
24698e099d14SDavid Gibson
2470992861fbSMarkus Armbruster if (!visit_start_struct(v, name, NULL, 0, errp)) {
2471992861fbSMarkus Armbruster return;
24728e099d14SDavid Gibson }
2473992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_year", &value.tm_year, errp)) {
24748e099d14SDavid Gibson goto out_end;
24758e099d14SDavid Gibson }
2476992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_mon", &value.tm_mon, errp)) {
24778e099d14SDavid Gibson goto out_end;
24788e099d14SDavid Gibson }
2479992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_mday", &value.tm_mday, errp)) {
24808e099d14SDavid Gibson goto out_end;
24818e099d14SDavid Gibson }
2482992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_hour", &value.tm_hour, errp)) {
24838e099d14SDavid Gibson goto out_end;
24848e099d14SDavid Gibson }
2485992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_min", &value.tm_min, errp)) {
24868e099d14SDavid Gibson goto out_end;
24878e099d14SDavid Gibson }
2488992861fbSMarkus Armbruster if (!visit_type_int32(v, "tm_sec", &value.tm_sec, errp)) {
24898e099d14SDavid Gibson goto out_end;
24908e099d14SDavid Gibson }
2491992861fbSMarkus Armbruster visit_check_struct(v, errp);
24928e099d14SDavid Gibson out_end:
24931158bb2aSEric Blake visit_end_struct(v, NULL);
24948e099d14SDavid Gibson }
24958e099d14SDavid Gibson
249670251887SMarkus Armbruster ObjectProperty *
object_property_add_tm(Object * obj,const char * name,void (* get)(Object *,struct tm *,Error **))249770251887SMarkus Armbruster object_property_add_tm(Object *obj, const char *name,
2498d2623129SMarkus Armbruster void (*get)(Object *, struct tm *, Error **))
24998e099d14SDavid Gibson {
25008e099d14SDavid Gibson TMProperty *prop = g_malloc0(sizeof(*prop));
25018e099d14SDavid Gibson
25028e099d14SDavid Gibson prop->get = get;
25038e099d14SDavid Gibson
2504d2623129SMarkus Armbruster return object_property_add(obj, name, "struct tm",
25058e099d14SDavid Gibson get ? property_get_tm : NULL, NULL,
2506169cbac1SPaolo Bonzini property_release_data,
2507d2623129SMarkus Armbruster prop);
25088e099d14SDavid Gibson }
25098e099d14SDavid Gibson
2510a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_tm(ObjectClass * klass,const char * name,void (* get)(Object *,struct tm *,Error **))2511a3a16211SMarc-André Lureau object_class_property_add_tm(ObjectClass *klass, const char *name,
2512d2623129SMarkus Armbruster void (*get)(Object *, struct tm *, Error **))
251316bf7f52SDaniel P. Berrange {
251416bf7f52SDaniel P. Berrange TMProperty *prop = g_malloc0(sizeof(*prop));
251516bf7f52SDaniel P. Berrange
251616bf7f52SDaniel P. Berrange prop->get = get;
251716bf7f52SDaniel P. Berrange
2518d2623129SMarkus Armbruster return object_class_property_add(klass, name, "struct tm",
2519d2623129SMarkus Armbruster get ? property_get_tm : NULL,
2520d2623129SMarkus Armbruster NULL, NULL, prop);
252116bf7f52SDaniel P. Berrange }
252216bf7f52SDaniel P. Berrange
object_get_type(Object * obj,Error ** errp)252390c69fb9SMarkus Armbruster static char *object_get_type(Object *obj, Error **errp)
25242f262e06SPaolo Bonzini {
25252f262e06SPaolo Bonzini return g_strdup(object_get_typename(obj));
25262f262e06SPaolo Bonzini }
25272f262e06SPaolo Bonzini
property_get_uint8_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2528d7bce999SEric Blake static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2529d7bce999SEric Blake void *opaque, Error **errp)
2530e732ea63SMichael S. Tsirkin {
2531e732ea63SMichael S. Tsirkin uint8_t value = *(uint8_t *)opaque;
253251e72bc1SEric Blake visit_type_uint8(v, name, &value, errp);
2533e732ea63SMichael S. Tsirkin }
2534e732ea63SMichael S. Tsirkin
property_set_uint8_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2535836e1b38SFelipe Franciosi static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
2536836e1b38SFelipe Franciosi void *opaque, Error **errp)
2537836e1b38SFelipe Franciosi {
2538836e1b38SFelipe Franciosi uint8_t *field = opaque;
2539836e1b38SFelipe Franciosi uint8_t value;
2540836e1b38SFelipe Franciosi
2541668f62ecSMarkus Armbruster if (!visit_type_uint8(v, name, &value, errp)) {
2542836e1b38SFelipe Franciosi return;
2543836e1b38SFelipe Franciosi }
2544836e1b38SFelipe Franciosi
2545836e1b38SFelipe Franciosi *field = value;
2546836e1b38SFelipe Franciosi }
2547836e1b38SFelipe Franciosi
property_get_uint16_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2548d7bce999SEric Blake static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2549d7bce999SEric Blake void *opaque, Error **errp)
2550e732ea63SMichael S. Tsirkin {
2551e732ea63SMichael S. Tsirkin uint16_t value = *(uint16_t *)opaque;
255251e72bc1SEric Blake visit_type_uint16(v, name, &value, errp);
2553e732ea63SMichael S. Tsirkin }
2554e732ea63SMichael S. Tsirkin
property_set_uint16_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2555836e1b38SFelipe Franciosi static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
2556836e1b38SFelipe Franciosi void *opaque, Error **errp)
2557836e1b38SFelipe Franciosi {
2558836e1b38SFelipe Franciosi uint16_t *field = opaque;
2559836e1b38SFelipe Franciosi uint16_t value;
2560836e1b38SFelipe Franciosi
2561668f62ecSMarkus Armbruster if (!visit_type_uint16(v, name, &value, errp)) {
2562836e1b38SFelipe Franciosi return;
2563836e1b38SFelipe Franciosi }
2564836e1b38SFelipe Franciosi
2565836e1b38SFelipe Franciosi *field = value;
2566836e1b38SFelipe Franciosi }
2567836e1b38SFelipe Franciosi
property_get_uint32_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2568d7bce999SEric Blake static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2569d7bce999SEric Blake void *opaque, Error **errp)
2570e732ea63SMichael S. Tsirkin {
2571e732ea63SMichael S. Tsirkin uint32_t value = *(uint32_t *)opaque;
257251e72bc1SEric Blake visit_type_uint32(v, name, &value, errp);
2573e732ea63SMichael S. Tsirkin }
2574e732ea63SMichael S. Tsirkin
property_set_uint32_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2575836e1b38SFelipe Franciosi static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
2576836e1b38SFelipe Franciosi void *opaque, Error **errp)
2577836e1b38SFelipe Franciosi {
2578836e1b38SFelipe Franciosi uint32_t *field = opaque;
2579836e1b38SFelipe Franciosi uint32_t value;
2580836e1b38SFelipe Franciosi
2581668f62ecSMarkus Armbruster if (!visit_type_uint32(v, name, &value, errp)) {
2582836e1b38SFelipe Franciosi return;
2583836e1b38SFelipe Franciosi }
2584836e1b38SFelipe Franciosi
2585836e1b38SFelipe Franciosi *field = value;
2586836e1b38SFelipe Franciosi }
2587836e1b38SFelipe Franciosi
property_get_uint64_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2588d7bce999SEric Blake static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2589d7bce999SEric Blake void *opaque, Error **errp)
2590e732ea63SMichael S. Tsirkin {
2591e732ea63SMichael S. Tsirkin uint64_t value = *(uint64_t *)opaque;
259251e72bc1SEric Blake visit_type_uint64(v, name, &value, errp);
2593e732ea63SMichael S. Tsirkin }
2594e732ea63SMichael S. Tsirkin
property_set_uint64_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2595836e1b38SFelipe Franciosi static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
2596836e1b38SFelipe Franciosi void *opaque, Error **errp)
2597e732ea63SMichael S. Tsirkin {
2598836e1b38SFelipe Franciosi uint64_t *field = opaque;
2599836e1b38SFelipe Franciosi uint64_t value;
2600836e1b38SFelipe Franciosi
2601668f62ecSMarkus Armbruster if (!visit_type_uint64(v, name, &value, errp)) {
2602836e1b38SFelipe Franciosi return;
2603836e1b38SFelipe Franciosi }
2604836e1b38SFelipe Franciosi
2605836e1b38SFelipe Franciosi *field = value;
2606836e1b38SFelipe Franciosi }
2607836e1b38SFelipe Franciosi
260870251887SMarkus Armbruster ObjectProperty *
object_property_add_uint8_ptr(Object * obj,const char * name,const uint8_t * v,ObjectPropertyFlags flags)260970251887SMarkus Armbruster object_property_add_uint8_ptr(Object *obj, const char *name,
2610836e1b38SFelipe Franciosi const uint8_t *v,
2611d2623129SMarkus Armbruster ObjectPropertyFlags flags)
2612836e1b38SFelipe Franciosi {
2613836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2614836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2615836e1b38SFelipe Franciosi
2616836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2617836e1b38SFelipe Franciosi getter = property_get_uint8_ptr;
2618836e1b38SFelipe Franciosi }
2619836e1b38SFelipe Franciosi
2620836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2621836e1b38SFelipe Franciosi setter = property_set_uint8_ptr;
2622836e1b38SFelipe Franciosi }
2623836e1b38SFelipe Franciosi
262470251887SMarkus Armbruster return object_property_add(obj, name, "uint8",
2625d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
2626e732ea63SMichael S. Tsirkin }
2627e732ea63SMichael S. Tsirkin
2628a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint8_ptr(ObjectClass * klass,const char * name,const uint8_t * v,ObjectPropertyFlags flags)2629a3a16211SMarc-André Lureau object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2630836e1b38SFelipe Franciosi const uint8_t *v,
2631d2623129SMarkus Armbruster ObjectPropertyFlags flags)
263216bf7f52SDaniel P. Berrange {
2633836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2634836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2635836e1b38SFelipe Franciosi
2636836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2637836e1b38SFelipe Franciosi getter = property_get_uint8_ptr;
2638836e1b38SFelipe Franciosi }
2639836e1b38SFelipe Franciosi
2640836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2641836e1b38SFelipe Franciosi setter = property_set_uint8_ptr;
2642836e1b38SFelipe Franciosi }
2643836e1b38SFelipe Franciosi
2644a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint8",
2645d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
264616bf7f52SDaniel P. Berrange }
264716bf7f52SDaniel P. Berrange
264870251887SMarkus Armbruster ObjectProperty *
object_property_add_uint16_ptr(Object * obj,const char * name,const uint16_t * v,ObjectPropertyFlags flags)264970251887SMarkus Armbruster object_property_add_uint16_ptr(Object *obj, const char *name,
2650836e1b38SFelipe Franciosi const uint16_t *v,
2651d2623129SMarkus Armbruster ObjectPropertyFlags flags)
2652e732ea63SMichael S. Tsirkin {
2653836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2654836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2655836e1b38SFelipe Franciosi
2656836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2657836e1b38SFelipe Franciosi getter = property_get_uint16_ptr;
2658836e1b38SFelipe Franciosi }
2659836e1b38SFelipe Franciosi
2660836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2661836e1b38SFelipe Franciosi setter = property_set_uint16_ptr;
2662836e1b38SFelipe Franciosi }
2663836e1b38SFelipe Franciosi
266470251887SMarkus Armbruster return object_property_add(obj, name, "uint16",
2665d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
2666e732ea63SMichael S. Tsirkin }
2667e732ea63SMichael S. Tsirkin
2668a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint16_ptr(ObjectClass * klass,const char * name,const uint16_t * v,ObjectPropertyFlags flags)2669a3a16211SMarc-André Lureau object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2670836e1b38SFelipe Franciosi const uint16_t *v,
2671d2623129SMarkus Armbruster ObjectPropertyFlags flags)
267216bf7f52SDaniel P. Berrange {
2673836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2674836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2675836e1b38SFelipe Franciosi
2676836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2677836e1b38SFelipe Franciosi getter = property_get_uint16_ptr;
2678836e1b38SFelipe Franciosi }
2679836e1b38SFelipe Franciosi
2680836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2681836e1b38SFelipe Franciosi setter = property_set_uint16_ptr;
2682836e1b38SFelipe Franciosi }
2683836e1b38SFelipe Franciosi
2684a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint16",
2685d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
268616bf7f52SDaniel P. Berrange }
268716bf7f52SDaniel P. Berrange
268870251887SMarkus Armbruster ObjectProperty *
object_property_add_uint32_ptr(Object * obj,const char * name,const uint32_t * v,ObjectPropertyFlags flags)268970251887SMarkus Armbruster object_property_add_uint32_ptr(Object *obj, const char *name,
2690836e1b38SFelipe Franciosi const uint32_t *v,
2691d2623129SMarkus Armbruster ObjectPropertyFlags flags)
2692e732ea63SMichael S. Tsirkin {
2693836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2694836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2695836e1b38SFelipe Franciosi
2696836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2697836e1b38SFelipe Franciosi getter = property_get_uint32_ptr;
2698836e1b38SFelipe Franciosi }
2699836e1b38SFelipe Franciosi
2700836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2701836e1b38SFelipe Franciosi setter = property_set_uint32_ptr;
2702836e1b38SFelipe Franciosi }
2703836e1b38SFelipe Franciosi
270470251887SMarkus Armbruster return object_property_add(obj, name, "uint32",
2705d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
2706e732ea63SMichael S. Tsirkin }
2707e732ea63SMichael S. Tsirkin
2708a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint32_ptr(ObjectClass * klass,const char * name,const uint32_t * v,ObjectPropertyFlags flags)2709a3a16211SMarc-André Lureau object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2710836e1b38SFelipe Franciosi const uint32_t *v,
2711d2623129SMarkus Armbruster ObjectPropertyFlags flags)
271216bf7f52SDaniel P. Berrange {
2713836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2714836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2715836e1b38SFelipe Franciosi
2716836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2717836e1b38SFelipe Franciosi getter = property_get_uint32_ptr;
2718836e1b38SFelipe Franciosi }
2719836e1b38SFelipe Franciosi
2720836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2721836e1b38SFelipe Franciosi setter = property_set_uint32_ptr;
2722836e1b38SFelipe Franciosi }
2723836e1b38SFelipe Franciosi
2724a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint32",
2725d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
272616bf7f52SDaniel P. Berrange }
272716bf7f52SDaniel P. Berrange
272870251887SMarkus Armbruster ObjectProperty *
object_property_add_uint64_ptr(Object * obj,const char * name,const uint64_t * v,ObjectPropertyFlags flags)272970251887SMarkus Armbruster object_property_add_uint64_ptr(Object *obj, const char *name,
2730836e1b38SFelipe Franciosi const uint64_t *v,
2731d2623129SMarkus Armbruster ObjectPropertyFlags flags)
2732e732ea63SMichael S. Tsirkin {
2733836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2734836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2735836e1b38SFelipe Franciosi
2736836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2737836e1b38SFelipe Franciosi getter = property_get_uint64_ptr;
2738836e1b38SFelipe Franciosi }
2739836e1b38SFelipe Franciosi
2740836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2741836e1b38SFelipe Franciosi setter = property_set_uint64_ptr;
2742836e1b38SFelipe Franciosi }
2743836e1b38SFelipe Franciosi
274470251887SMarkus Armbruster return object_property_add(obj, name, "uint64",
2745d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
2746e732ea63SMichael S. Tsirkin }
2747e732ea63SMichael S. Tsirkin
2748a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint64_ptr(ObjectClass * klass,const char * name,const uint64_t * v,ObjectPropertyFlags flags)2749a3a16211SMarc-André Lureau object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2750836e1b38SFelipe Franciosi const uint64_t *v,
2751d2623129SMarkus Armbruster ObjectPropertyFlags flags)
275216bf7f52SDaniel P. Berrange {
2753836e1b38SFelipe Franciosi ObjectPropertyAccessor *getter = NULL;
2754836e1b38SFelipe Franciosi ObjectPropertyAccessor *setter = NULL;
2755836e1b38SFelipe Franciosi
2756836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2757836e1b38SFelipe Franciosi getter = property_get_uint64_ptr;
2758836e1b38SFelipe Franciosi }
2759836e1b38SFelipe Franciosi
2760836e1b38SFelipe Franciosi if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2761836e1b38SFelipe Franciosi setter = property_set_uint64_ptr;
2762836e1b38SFelipe Franciosi }
2763836e1b38SFelipe Franciosi
2764a3a16211SMarc-André Lureau return object_class_property_add(klass, name, "uint64",
2765d2623129SMarkus Armbruster getter, setter, NULL, (void *)v);
276616bf7f52SDaniel P. Berrange }
276716bf7f52SDaniel P. Berrange
2768ef7c7ff6SStefan Hajnoczi typedef struct {
2769ef7c7ff6SStefan Hajnoczi Object *target_obj;
27701590d266SEduardo Habkost char *target_name;
2771ef7c7ff6SStefan Hajnoczi } AliasProperty;
2772ef7c7ff6SStefan Hajnoczi
property_get_alias(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2773d7bce999SEric Blake static void property_get_alias(Object *obj, Visitor *v, const char *name,
2774d7bce999SEric Blake void *opaque, Error **errp)
2775ef7c7ff6SStefan Hajnoczi {
2776ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque;
2777cbc94d97SPaolo Bonzini Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2778ef7c7ff6SStefan Hajnoczi
2779cbc94d97SPaolo Bonzini object_property_get(prop->target_obj, prop->target_name, alias_v, errp);
2780cbc94d97SPaolo Bonzini visit_free(alias_v);
2781ef7c7ff6SStefan Hajnoczi }
2782ef7c7ff6SStefan Hajnoczi
property_set_alias(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2783d7bce999SEric Blake static void property_set_alias(Object *obj, Visitor *v, const char *name,
2784d7bce999SEric Blake void *opaque, Error **errp)
2785ef7c7ff6SStefan Hajnoczi {
2786ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque;
2787cbc94d97SPaolo Bonzini Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2788ef7c7ff6SStefan Hajnoczi
2789cbc94d97SPaolo Bonzini object_property_set(prop->target_obj, prop->target_name, alias_v, errp);
2790cbc94d97SPaolo Bonzini visit_free(alias_v);
2791ef7c7ff6SStefan Hajnoczi }
2792ef7c7ff6SStefan Hajnoczi
property_resolve_alias(Object * obj,void * opaque,const char * part)279364607d08SPaolo Bonzini static Object *property_resolve_alias(Object *obj, void *opaque,
2794ddfb0baaSMarkus Armbruster const char *part)
279564607d08SPaolo Bonzini {
279664607d08SPaolo Bonzini AliasProperty *prop = opaque;
279764607d08SPaolo Bonzini
279864607d08SPaolo Bonzini return object_resolve_path_component(prop->target_obj, prop->target_name);
279964607d08SPaolo Bonzini }
280064607d08SPaolo Bonzini
property_release_alias(Object * obj,const char * name,void * opaque)2801ef7c7ff6SStefan Hajnoczi static void property_release_alias(Object *obj, const char *name, void *opaque)
2802ef7c7ff6SStefan Hajnoczi {
2803ef7c7ff6SStefan Hajnoczi AliasProperty *prop = opaque;
2804ef7c7ff6SStefan Hajnoczi
28051590d266SEduardo Habkost g_free(prop->target_name);
2806ef7c7ff6SStefan Hajnoczi g_free(prop);
2807ef7c7ff6SStefan Hajnoczi }
2808ef7c7ff6SStefan Hajnoczi
280970251887SMarkus Armbruster ObjectProperty *
object_property_add_alias(Object * obj,const char * name,Object * target_obj,const char * target_name)281070251887SMarkus Armbruster object_property_add_alias(Object *obj, const char *name,
2811d2623129SMarkus Armbruster Object *target_obj, const char *target_name)
2812ef7c7ff6SStefan Hajnoczi {
2813ef7c7ff6SStefan Hajnoczi AliasProperty *prop;
281464607d08SPaolo Bonzini ObjectProperty *op;
2815ef7c7ff6SStefan Hajnoczi ObjectProperty *target_prop;
281670251887SMarkus Armbruster g_autofree char *prop_type = NULL;
2817ef7c7ff6SStefan Hajnoczi
2818efba1595SDaniel P. Berrangé target_prop = object_property_find_err(target_obj, target_name,
2819d2623129SMarkus Armbruster &error_abort);
2820ef7c7ff6SStefan Hajnoczi
2821d190698eSPaolo Bonzini if (object_property_is_child(target_prop)) {
2822d190698eSPaolo Bonzini prop_type = g_strdup_printf("link%s",
2823d190698eSPaolo Bonzini target_prop->type + strlen("child"));
2824d190698eSPaolo Bonzini } else {
2825d190698eSPaolo Bonzini prop_type = g_strdup(target_prop->type);
2826d190698eSPaolo Bonzini }
2827d190698eSPaolo Bonzini
2828ef7c7ff6SStefan Hajnoczi prop = g_malloc(sizeof(*prop));
2829ef7c7ff6SStefan Hajnoczi prop->target_obj = target_obj;
28301590d266SEduardo Habkost prop->target_name = g_strdup(target_name);
2831ef7c7ff6SStefan Hajnoczi
2832d190698eSPaolo Bonzini op = object_property_add(obj, name, prop_type,
2833ef7c7ff6SStefan Hajnoczi property_get_alias,
2834ef7c7ff6SStefan Hajnoczi property_set_alias,
2835ef7c7ff6SStefan Hajnoczi property_release_alias,
2836d2623129SMarkus Armbruster prop);
283764607d08SPaolo Bonzini op->resolve = property_resolve_alias;
28380e76ed0aSMarc-André Lureau if (target_prop->defval) {
28390e76ed0aSMarc-André Lureau op->defval = qobject_ref(target_prop->defval);
28400e76ed0aSMarc-André Lureau }
2841d190698eSPaolo Bonzini
2842a18bb417SAndreas Färber object_property_set_description(obj, op->name,
28437eecec7dSMarkus Armbruster target_prop->description);
284470251887SMarkus Armbruster return op;
2845ef7c7ff6SStefan Hajnoczi }
2846ef7c7ff6SStefan Hajnoczi
object_property_set_description(Object * obj,const char * name,const char * description)284780742642SGonglei void object_property_set_description(Object *obj, const char *name,
28487eecec7dSMarkus Armbruster const char *description)
284980742642SGonglei {
285080742642SGonglei ObjectProperty *op;
285180742642SGonglei
2852efba1595SDaniel P. Berrangé op = object_property_find_err(obj, name, &error_abort);
285380742642SGonglei g_free(op->description);
285480742642SGonglei op->description = g_strdup(description);
285580742642SGonglei }
285680742642SGonglei
object_class_property_set_description(ObjectClass * klass,const char * name,const char * description)285716bf7f52SDaniel P. Berrange void object_class_property_set_description(ObjectClass *klass,
285816bf7f52SDaniel P. Berrange const char *name,
28597eecec7dSMarkus Armbruster const char *description)
286016bf7f52SDaniel P. Berrange {
286116bf7f52SDaniel P. Berrange ObjectProperty *op;
286216bf7f52SDaniel P. Berrange
286316bf7f52SDaniel P. Berrange op = g_hash_table_lookup(klass->properties, name);
286416bf7f52SDaniel P. Berrange g_free(op->description);
286516bf7f52SDaniel P. Berrange op->description = g_strdup(description);
286616bf7f52SDaniel P. Berrange }
286716bf7f52SDaniel P. Berrange
object_class_init(ObjectClass * klass,void * data)28687439a036SMarc-André Lureau static void object_class_init(ObjectClass *klass, void *data)
28692f262e06SPaolo Bonzini {
287090c69fb9SMarkus Armbruster object_class_property_add_str(klass, "type", object_get_type,
2871d2623129SMarkus Armbruster NULL);
28722f262e06SPaolo Bonzini }
28732f262e06SPaolo Bonzini
register_types(void)2874745549c8SPaolo Bonzini static void register_types(void)
2875745549c8SPaolo Bonzini {
28765e78c98bSBernhard Beschow static const TypeInfo interface_info = {
2877745549c8SPaolo Bonzini .name = TYPE_INTERFACE,
287833e95c63SAnthony Liguori .class_size = sizeof(InterfaceClass),
2879745549c8SPaolo Bonzini .abstract = true,
2880745549c8SPaolo Bonzini };
2881745549c8SPaolo Bonzini
28825e78c98bSBernhard Beschow static const TypeInfo object_info = {
2883745549c8SPaolo Bonzini .name = TYPE_OBJECT,
2884745549c8SPaolo Bonzini .instance_size = sizeof(Object),
28857439a036SMarc-André Lureau .class_init = object_class_init,
2886745549c8SPaolo Bonzini .abstract = true,
2887745549c8SPaolo Bonzini };
2888745549c8SPaolo Bonzini
2889049cb3cfSPaolo Bonzini type_interface = type_register_internal(&interface_info);
2890049cb3cfSPaolo Bonzini type_register_internal(&object_info);
2891745549c8SPaolo Bonzini }
2892745549c8SPaolo Bonzini
2893745549c8SPaolo Bonzini type_init(register_types)
2894