xref: /qemu/qom/object.c (revision ef929281)
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     /* Allow some legacy names with '+' in it for compatibility reasons */
161b447378eSThomas Huth     if (name[plen] == '+') {
162b447378eSThomas Huth         if (plen >= 17 && g_str_has_prefix(name, "Sun-UltraSparc-I")) {
163b447378eSThomas Huth             /* Allow "Sun-UltraSparc-IV+" and "Sun-UltraSparc-IIIi+" */
164b447378eSThomas Huth             return true;
165b447378eSThomas Huth         }
166b447378eSThomas Huth     }
167b447378eSThomas Huth 
168b447378eSThomas Huth     return plen == slen;
169b447378eSThomas Huth }
170b447378eSThomas Huth 
type_register_internal(const TypeInfo * info)171b061dc41SPaolo Bonzini static TypeImpl *type_register_internal(const TypeInfo *info)
172b061dc41SPaolo Bonzini {
173b061dc41SPaolo Bonzini     TypeImpl *ti;
174b447378eSThomas Huth 
175b447378eSThomas Huth     if (!type_name_is_valid(info->name)) {
176b447378eSThomas Huth         fprintf(stderr, "Registering '%s' with illegal type name\n", info->name);
177b447378eSThomas Huth         abort();
178b447378eSThomas Huth     }
179b447378eSThomas Huth 
180b061dc41SPaolo Bonzini     ti = type_new(info);
181b061dc41SPaolo Bonzini 
182b061dc41SPaolo Bonzini     type_table_add(ti);
1832f28d2ffSAnthony Liguori     return ti;
1842f28d2ffSAnthony Liguori }
1852f28d2ffSAnthony Liguori 
type_register(const TypeInfo * info)186049cb3cfSPaolo Bonzini TypeImpl *type_register(const TypeInfo *info)
187049cb3cfSPaolo Bonzini {
188049cb3cfSPaolo Bonzini     assert(info->parent);
189049cb3cfSPaolo Bonzini     return type_register_internal(info);
190049cb3cfSPaolo Bonzini }
191049cb3cfSPaolo Bonzini 
type_register_static(const TypeInfo * info)1922f28d2ffSAnthony Liguori TypeImpl *type_register_static(const TypeInfo *info)
1932f28d2ffSAnthony Liguori {
1942f28d2ffSAnthony Liguori     return type_register(info);
1952f28d2ffSAnthony Liguori }
1962f28d2ffSAnthony Liguori 
type_register_static_array(const TypeInfo * infos,int nr_infos)197aa04c9d2SIgor Mammedov void type_register_static_array(const TypeInfo *infos, int nr_infos)
198aa04c9d2SIgor Mammedov {
199aa04c9d2SIgor Mammedov     int i;
200aa04c9d2SIgor Mammedov 
201aa04c9d2SIgor Mammedov     for (i = 0; i < nr_infos; i++) {
202aa04c9d2SIgor Mammedov         type_register_static(&infos[i]);
203aa04c9d2SIgor Mammedov     }
204aa04c9d2SIgor Mammedov }
205aa04c9d2SIgor Mammedov 
type_get_by_name(const char * name)2062f28d2ffSAnthony Liguori static TypeImpl *type_get_by_name(const char *name)
2072f28d2ffSAnthony Liguori {
2082f28d2ffSAnthony Liguori     if (name == NULL) {
2092f28d2ffSAnthony Liguori         return NULL;
2102f28d2ffSAnthony Liguori     }
2112f28d2ffSAnthony Liguori 
2122f28d2ffSAnthony Liguori     return type_table_lookup(name);
2132f28d2ffSAnthony Liguori }
2142f28d2ffSAnthony Liguori 
type_get_parent(TypeImpl * type)2152f28d2ffSAnthony Liguori static TypeImpl *type_get_parent(TypeImpl *type)
2162f28d2ffSAnthony Liguori {
2172f28d2ffSAnthony Liguori     if (!type->parent_type && type->parent) {
2182f28d2ffSAnthony Liguori         type->parent_type = type_get_by_name(type->parent);
21989d337fdSPhilippe Mathieu-Daudé         if (!type->parent_type) {
22089d337fdSPhilippe Mathieu-Daudé             fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
22189d337fdSPhilippe Mathieu-Daudé                     type->name, type->parent);
22289d337fdSPhilippe Mathieu-Daudé             abort();
22389d337fdSPhilippe Mathieu-Daudé         }
2242f28d2ffSAnthony Liguori     }
2252f28d2ffSAnthony Liguori 
2262f28d2ffSAnthony Liguori     return type->parent_type;
2272f28d2ffSAnthony Liguori }
2282f28d2ffSAnthony Liguori 
type_has_parent(TypeImpl * type)2292f28d2ffSAnthony Liguori static bool type_has_parent(TypeImpl *type)
2302f28d2ffSAnthony Liguori {
2312f28d2ffSAnthony Liguori     return (type->parent != NULL);
2322f28d2ffSAnthony Liguori }
2332f28d2ffSAnthony Liguori 
type_class_get_size(TypeImpl * ti)2342f28d2ffSAnthony Liguori static size_t type_class_get_size(TypeImpl *ti)
2352f28d2ffSAnthony Liguori {
2362f28d2ffSAnthony Liguori     if (ti->class_size) {
2372f28d2ffSAnthony Liguori         return ti->class_size;
2382f28d2ffSAnthony Liguori     }
2392f28d2ffSAnthony Liguori 
2402f28d2ffSAnthony Liguori     if (type_has_parent(ti)) {
2412f28d2ffSAnthony Liguori         return type_class_get_size(type_get_parent(ti));
2422f28d2ffSAnthony Liguori     }
2432f28d2ffSAnthony Liguori 
2442f28d2ffSAnthony Liguori     return sizeof(ObjectClass);
2452f28d2ffSAnthony Liguori }
2462f28d2ffSAnthony Liguori 
type_object_get_size(TypeImpl * ti)247aca59af6SIgor Mitsyanko static size_t type_object_get_size(TypeImpl *ti)
248aca59af6SIgor Mitsyanko {
249aca59af6SIgor Mitsyanko     if (ti->instance_size) {
250aca59af6SIgor Mitsyanko         return ti->instance_size;
251aca59af6SIgor Mitsyanko     }
252aca59af6SIgor Mitsyanko 
253aca59af6SIgor Mitsyanko     if (type_has_parent(ti)) {
254aca59af6SIgor Mitsyanko         return type_object_get_size(type_get_parent(ti));
255aca59af6SIgor Mitsyanko     }
256aca59af6SIgor Mitsyanko 
257aca59af6SIgor Mitsyanko     return 0;
258aca59af6SIgor Mitsyanko }
259aca59af6SIgor Mitsyanko 
type_object_get_align(TypeImpl * ti)260ad4ec279SRichard Henderson static size_t type_object_get_align(TypeImpl *ti)
261ad4ec279SRichard Henderson {
262ad4ec279SRichard Henderson     if (ti->instance_align) {
263ad4ec279SRichard Henderson         return ti->instance_align;
264ad4ec279SRichard Henderson     }
265ad4ec279SRichard Henderson 
266ad4ec279SRichard Henderson     if (type_has_parent(ti)) {
267ad4ec279SRichard Henderson         return type_object_get_align(type_get_parent(ti));
268ad4ec279SRichard Henderson     }
269ad4ec279SRichard Henderson 
270ad4ec279SRichard Henderson     return 0;
271ad4ec279SRichard Henderson }
272ad4ec279SRichard Henderson 
object_type_get_instance_size(const char * typename)2733f97b53aSBharata B Rao size_t object_type_get_instance_size(const char *typename)
2743f97b53aSBharata B Rao {
2753f97b53aSBharata B Rao     TypeImpl *type = type_get_by_name(typename);
2763f97b53aSBharata B Rao 
2773f97b53aSBharata B Rao     g_assert(type != NULL);
2783f97b53aSBharata B Rao     return type_object_get_size(type);
2793f97b53aSBharata B Rao }
2803f97b53aSBharata B Rao 
type_is_ancestor(TypeImpl * type,TypeImpl * target_type)28133e95c63SAnthony Liguori static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
2822f28d2ffSAnthony Liguori {
28333e95c63SAnthony Liguori     assert(target_type);
2842f28d2ffSAnthony Liguori 
285b30d8054SCao jin     /* Check if target_type is a direct ancestor of type */
28633e95c63SAnthony Liguori     while (type) {
28733e95c63SAnthony Liguori         if (type == target_type) {
28833e95c63SAnthony Liguori             return true;
28933e95c63SAnthony Liguori         }
29033e95c63SAnthony Liguori 
29133e95c63SAnthony Liguori         type = type_get_parent(type);
29233e95c63SAnthony Liguori     }
29333e95c63SAnthony Liguori 
29433e95c63SAnthony Liguori     return false;
29533e95c63SAnthony Liguori }
29633e95c63SAnthony Liguori 
29733e95c63SAnthony Liguori static void type_initialize(TypeImpl *ti);
29833e95c63SAnthony Liguori 
type_initialize_interface(TypeImpl * ti,TypeImpl * interface_type,TypeImpl * parent_type)299b061dc41SPaolo Bonzini static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
300b061dc41SPaolo Bonzini                                       TypeImpl *parent_type)
30133e95c63SAnthony Liguori {
30233e95c63SAnthony Liguori     InterfaceClass *new_iface;
30333e95c63SAnthony Liguori     TypeInfo info = { };
30433e95c63SAnthony Liguori     TypeImpl *iface_impl;
30533e95c63SAnthony Liguori 
306b061dc41SPaolo Bonzini     info.parent = parent_type->name;
307b061dc41SPaolo Bonzini     info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
30833e95c63SAnthony Liguori     info.abstract = true;
30933e95c63SAnthony Liguori 
310b061dc41SPaolo Bonzini     iface_impl = type_new(&info);
311b061dc41SPaolo Bonzini     iface_impl->parent_type = parent_type;
31233e95c63SAnthony Liguori     type_initialize(iface_impl);
31333e95c63SAnthony Liguori     g_free((char *)info.name);
31433e95c63SAnthony Liguori 
31533e95c63SAnthony Liguori     new_iface = (InterfaceClass *)iface_impl->class;
31633e95c63SAnthony Liguori     new_iface->concrete_class = ti->class;
317b061dc41SPaolo Bonzini     new_iface->interface_type = interface_type;
31833e95c63SAnthony Liguori 
3193d91293eSMasahiro Yamada     ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface);
3202f28d2ffSAnthony Liguori }
3212f28d2ffSAnthony Liguori 
object_property_free(gpointer data)32216bf7f52SDaniel P. Berrange static void object_property_free(gpointer data)
32316bf7f52SDaniel P. Berrange {
32416bf7f52SDaniel P. Berrange     ObjectProperty *prop = data;
32516bf7f52SDaniel P. Berrange 
3260e76ed0aSMarc-André Lureau     if (prop->defval) {
3270e76ed0aSMarc-André Lureau         qobject_unref(prop->defval);
3280e76ed0aSMarc-André Lureau         prop->defval = NULL;
3290e76ed0aSMarc-André Lureau     }
33016bf7f52SDaniel P. Berrange     g_free(prop->name);
33116bf7f52SDaniel P. Berrange     g_free(prop->type);
33216bf7f52SDaniel P. Berrange     g_free(prop->description);
33316bf7f52SDaniel P. Berrange     g_free(prop);
33416bf7f52SDaniel P. Berrange }
33516bf7f52SDaniel P. Berrange 
type_initialize(TypeImpl * ti)336ac451033SIgor Mitsyanko static void type_initialize(TypeImpl *ti)
3372f28d2ffSAnthony Liguori {
338745549c8SPaolo Bonzini     TypeImpl *parent;
3392f28d2ffSAnthony Liguori 
3402f28d2ffSAnthony Liguori     if (ti->class) {
3412f28d2ffSAnthony Liguori         return;
3422f28d2ffSAnthony Liguori     }
3432f28d2ffSAnthony Liguori 
3442f28d2ffSAnthony Liguori     ti->class_size = type_class_get_size(ti);
345aca59af6SIgor Mitsyanko     ti->instance_size = type_object_get_size(ti);
346ad4ec279SRichard Henderson     ti->instance_align = type_object_get_align(ti);
3471c6d75d5SEduardo Habkost     /* Any type with zero instance_size is implicitly abstract.
3481c6d75d5SEduardo Habkost      * This means interface types are all abstract.
3491c6d75d5SEduardo Habkost      */
3501c6d75d5SEduardo Habkost     if (ti->instance_size == 0) {
3511c6d75d5SEduardo Habkost         ti->abstract = true;
3521c6d75d5SEduardo Habkost     }
353422ca143SMarc-André Lureau     if (type_is_ancestor(ti, type_interface)) {
354422ca143SMarc-André Lureau         assert(ti->instance_size == 0);
355422ca143SMarc-André Lureau         assert(ti->abstract);
356422ca143SMarc-André Lureau         assert(!ti->instance_init);
357422ca143SMarc-André Lureau         assert(!ti->instance_post_init);
358422ca143SMarc-André Lureau         assert(!ti->instance_finalize);
359422ca143SMarc-André Lureau         assert(!ti->num_interfaces);
360422ca143SMarc-André Lureau     }
3612f28d2ffSAnthony Liguori     ti->class = g_malloc0(ti->class_size);
3622f28d2ffSAnthony Liguori 
363745549c8SPaolo Bonzini     parent = type_get_parent(ti);
364745549c8SPaolo Bonzini     if (parent) {
365ac451033SIgor Mitsyanko         type_initialize(parent);
36633e95c63SAnthony Liguori         GSList *e;
36733e95c63SAnthony Liguori         int i;
3682f28d2ffSAnthony Liguori 
369719a3077SMarkus Armbruster         g_assert(parent->class_size <= ti->class_size);
370d5e633fcSMarc-André Lureau         g_assert(parent->instance_size <= ti->instance_size);
371745549c8SPaolo Bonzini         memcpy(ti->class, parent->class, parent->class_size);
3723e407de4SPeter Crosthwaite         ti->class->interfaces = NULL;
37333e95c63SAnthony Liguori 
37433e95c63SAnthony Liguori         for (e = parent->class->interfaces; e; e = e->next) {
375b061dc41SPaolo Bonzini             InterfaceClass *iface = e->data;
376b061dc41SPaolo Bonzini             ObjectClass *klass = OBJECT_CLASS(iface);
377b061dc41SPaolo Bonzini 
378b061dc41SPaolo Bonzini             type_initialize_interface(ti, iface->interface_type, klass->type);
37933e95c63SAnthony Liguori         }
38033e95c63SAnthony Liguori 
38133e95c63SAnthony Liguori         for (i = 0; i < ti->num_interfaces; i++) {
38233e95c63SAnthony Liguori             TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
383a9ee3a9eSPhilippe Mathieu-Daudé             if (!t) {
384a9ee3a9eSPhilippe Mathieu-Daudé                 error_report("missing interface '%s' for object '%s'",
385a9ee3a9eSPhilippe Mathieu-Daudé                              ti->interfaces[i].typename, parent->name);
386a9ee3a9eSPhilippe Mathieu-Daudé                 abort();
387a9ee3a9eSPhilippe Mathieu-Daudé             }
38833e95c63SAnthony Liguori             for (e = ti->class->interfaces; e; e = e->next) {
38933e95c63SAnthony Liguori                 TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
39033e95c63SAnthony Liguori 
39133e95c63SAnthony Liguori                 if (type_is_ancestor(target_type, t)) {
39233e95c63SAnthony Liguori                     break;
39333e95c63SAnthony Liguori                 }
39433e95c63SAnthony Liguori             }
39533e95c63SAnthony Liguori 
39633e95c63SAnthony Liguori             if (e) {
39733e95c63SAnthony Liguori                 continue;
39833e95c63SAnthony Liguori             }
39933e95c63SAnthony Liguori 
400b061dc41SPaolo Bonzini             type_initialize_interface(ti, t, t);
40133e95c63SAnthony Liguori         }
402745549c8SPaolo Bonzini     }
4032f28d2ffSAnthony Liguori 
404e5a0cc5eSMasahiro Yamada     ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
405e5a0cc5eSMasahiro Yamada                                                   object_property_free);
406e5a0cc5eSMasahiro Yamada 
407745549c8SPaolo Bonzini     ti->class->type = ti;
4083b50e311SPaolo Bonzini 
4093b50e311SPaolo Bonzini     while (parent) {
4103b50e311SPaolo Bonzini         if (parent->class_base_init) {
4113b50e311SPaolo Bonzini             parent->class_base_init(ti->class, ti->class_data);
4123b50e311SPaolo Bonzini         }
4133b50e311SPaolo Bonzini         parent = type_get_parent(parent);
4143b50e311SPaolo Bonzini     }
4152f28d2ffSAnthony Liguori 
4162f28d2ffSAnthony Liguori     if (ti->class_init) {
4172f28d2ffSAnthony Liguori         ti->class_init(ti->class, ti->class_data);
4182f28d2ffSAnthony Liguori     }
4192f28d2ffSAnthony Liguori }
4202f28d2ffSAnthony Liguori 
object_init_with_type(Object * obj,TypeImpl * ti)4212f28d2ffSAnthony Liguori static void object_init_with_type(Object *obj, TypeImpl *ti)
4222f28d2ffSAnthony Liguori {
4232f28d2ffSAnthony Liguori     if (type_has_parent(ti)) {
4242f28d2ffSAnthony Liguori         object_init_with_type(obj, type_get_parent(ti));
4252f28d2ffSAnthony Liguori     }
4262f28d2ffSAnthony Liguori 
4272f28d2ffSAnthony Liguori     if (ti->instance_init) {
4282f28d2ffSAnthony Liguori         ti->instance_init(obj);
4292f28d2ffSAnthony Liguori     }
4302f28d2ffSAnthony Liguori }
4312f28d2ffSAnthony Liguori 
object_post_init_with_type(Object * obj,TypeImpl * ti)4328231c2ddSEduardo Habkost static void object_post_init_with_type(Object *obj, TypeImpl *ti)
4338231c2ddSEduardo Habkost {
4348231c2ddSEduardo Habkost     if (ti->instance_post_init) {
4358231c2ddSEduardo Habkost         ti->instance_post_init(obj);
4368231c2ddSEduardo Habkost     }
4378231c2ddSEduardo Habkost 
4388231c2ddSEduardo Habkost     if (type_has_parent(ti)) {
4398231c2ddSEduardo Habkost         object_post_init_with_type(obj, type_get_parent(ti));
4408231c2ddSEduardo Habkost     }
4418231c2ddSEduardo Habkost }
4428231c2ddSEduardo Habkost 
object_apply_global_props(Object * obj,const GPtrArray * props,Error ** errp)4436fd5bef1SMarkus Armbruster bool object_apply_global_props(Object *obj, const GPtrArray *props,
4446fd5bef1SMarkus Armbruster                                Error **errp)
445ea9ce893SMarc-André Lureau {
446ea9ce893SMarc-André Lureau     int i;
447ea9ce893SMarc-André Lureau 
448ea9ce893SMarc-André Lureau     if (!props) {
4496fd5bef1SMarkus Armbruster         return true;
450ea9ce893SMarc-André Lureau     }
451ea9ce893SMarc-André Lureau 
452ea9ce893SMarc-André Lureau     for (i = 0; i < props->len; i++) {
453ea9ce893SMarc-André Lureau         GlobalProperty *p = g_ptr_array_index(props, i);
454d769f0dfSEduardo Habkost         Error *err = NULL;
455ea9ce893SMarc-André Lureau 
456ea9ce893SMarc-André Lureau         if (object_dynamic_cast(obj, p->driver) == NULL) {
457ea9ce893SMarc-André Lureau             continue;
458ea9ce893SMarc-André Lureau         }
459efba1595SDaniel P. Berrangé         if (p->optional && !object_property_find(obj, p->property)) {
46092fd453cSDr. David Alan Gilbert             continue;
46192fd453cSDr. David Alan Gilbert         }
462ea9ce893SMarc-André Lureau         p->used = true;
463778a2dc5SMarkus Armbruster         if (!object_property_parse(obj, p->property, p->value, &err)) {
464ea9ce893SMarc-André Lureau             error_prepend(&err, "can't apply global %s.%s=%s: ",
465ea9ce893SMarc-André Lureau                           p->driver, p->property, p->value);
46650545b2cSMarc-André Lureau             /*
46750545b2cSMarc-André Lureau              * If errp != NULL, propagate error and return.
46850545b2cSMarc-André Lureau              * If errp == NULL, report a warning, but keep going
46950545b2cSMarc-André Lureau              * with the remaining globals.
47050545b2cSMarc-André Lureau              */
47150545b2cSMarc-André Lureau             if (errp) {
472ea9ce893SMarc-André Lureau                 error_propagate(errp, err);
4736fd5bef1SMarkus Armbruster                 return false;
47450545b2cSMarc-André Lureau             } else {
47550545b2cSMarc-André Lureau                 warn_report_err(err);
47650545b2cSMarc-André Lureau             }
477ea9ce893SMarc-André Lureau         }
478ea9ce893SMarc-André Lureau     }
4796fd5bef1SMarkus Armbruster 
4806fd5bef1SMarkus Armbruster     return true;
481ea9ce893SMarc-André Lureau }
482ea9ce893SMarc-André Lureau 
483617902afSMarkus Armbruster /*
484617902afSMarkus Armbruster  * Global property defaults
485617902afSMarkus Armbruster  * Slot 0: accelerator's global property defaults
486617902afSMarkus Armbruster  * Slot 1: machine's global property defaults
4871fff3c20SPaolo Bonzini  * Slot 2: global properties from legacy command line option
488617902afSMarkus Armbruster  * Each is a GPtrArray of of GlobalProperty.
489617902afSMarkus Armbruster  * Applied in order, later entries override earlier ones.
490617902afSMarkus Armbruster  */
4911fff3c20SPaolo Bonzini static GPtrArray *object_compat_props[3];
4921fff3c20SPaolo Bonzini 
4931fff3c20SPaolo Bonzini /*
4941fff3c20SPaolo Bonzini  * Retrieve @GPtrArray for global property defined with options
4951fff3c20SPaolo Bonzini  * other than "-global".  These are generally used for syntactic
4961fff3c20SPaolo Bonzini  * sugar and legacy command line options.
4971fff3c20SPaolo Bonzini  */
object_register_sugar_prop(const char * driver,const char * prop,const char * value,bool optional)498a8dc82ceSGreg Kurz void object_register_sugar_prop(const char *driver, const char *prop,
499a8dc82ceSGreg Kurz                                 const char *value, bool optional)
5001fff3c20SPaolo Bonzini {
5011fff3c20SPaolo Bonzini     GlobalProperty *g;
5021fff3c20SPaolo Bonzini     if (!object_compat_props[2]) {
5031fff3c20SPaolo Bonzini         object_compat_props[2] = g_ptr_array_new();
5041fff3c20SPaolo Bonzini     }
5051fff3c20SPaolo Bonzini     g = g_new0(GlobalProperty, 1);
5061fff3c20SPaolo Bonzini     g->driver = g_strdup(driver);
5071fff3c20SPaolo Bonzini     g->property = g_strdup(prop);
5081fff3c20SPaolo Bonzini     g->value = g_strdup(value);
509a8dc82ceSGreg Kurz     g->optional = optional;
5101fff3c20SPaolo Bonzini     g_ptr_array_add(object_compat_props[2], g);
5111fff3c20SPaolo Bonzini }
512617902afSMarkus Armbruster 
513617902afSMarkus Armbruster /*
514617902afSMarkus Armbruster  * Set machine's global property defaults to @compat_props.
515617902afSMarkus Armbruster  * May be called at most once.
516617902afSMarkus Armbruster  */
object_set_machine_compat_props(GPtrArray * compat_props)517617902afSMarkus Armbruster void object_set_machine_compat_props(GPtrArray *compat_props)
518617902afSMarkus Armbruster {
519617902afSMarkus Armbruster     assert(!object_compat_props[1]);
520617902afSMarkus Armbruster     object_compat_props[1] = compat_props;
521617902afSMarkus Armbruster }
522617902afSMarkus Armbruster 
523617902afSMarkus Armbruster /*
524617902afSMarkus Armbruster  * Set accelerator's global property defaults to @compat_props.
525617902afSMarkus Armbruster  * May be called at most once.
526617902afSMarkus Armbruster  */
object_set_accelerator_compat_props(GPtrArray * compat_props)527617902afSMarkus Armbruster void object_set_accelerator_compat_props(GPtrArray *compat_props)
528617902afSMarkus Armbruster {
529617902afSMarkus Armbruster     assert(!object_compat_props[0]);
530617902afSMarkus Armbruster     object_compat_props[0] = compat_props;
531617902afSMarkus Armbruster }
532617902afSMarkus Armbruster 
object_apply_compat_props(Object * obj)533617902afSMarkus Armbruster void object_apply_compat_props(Object *obj)
534617902afSMarkus Armbruster {
535617902afSMarkus Armbruster     int i;
536617902afSMarkus Armbruster 
537617902afSMarkus Armbruster     for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
538617902afSMarkus Armbruster         object_apply_global_props(obj, object_compat_props[i],
5391fff3c20SPaolo Bonzini                                   i == 2 ? &error_fatal : &error_abort);
540617902afSMarkus Armbruster     }
541617902afSMarkus Armbruster }
542617902afSMarkus Armbruster 
object_class_property_init_all(Object * obj)5432a1be4b3SMarc-André Lureau static void object_class_property_init_all(Object *obj)
5442a1be4b3SMarc-André Lureau {
5452a1be4b3SMarc-André Lureau     ObjectPropertyIterator iter;
5462a1be4b3SMarc-André Lureau     ObjectProperty *prop;
5472a1be4b3SMarc-André Lureau 
5482a1be4b3SMarc-André Lureau     object_class_property_iter_init(&iter, object_get_class(obj));
5492a1be4b3SMarc-André Lureau     while ((prop = object_property_iter_next(&iter))) {
5502a1be4b3SMarc-André Lureau         if (prop->init) {
5512a1be4b3SMarc-André Lureau             prop->init(obj, prop);
5522a1be4b3SMarc-André Lureau         }
5532a1be4b3SMarc-André Lureau     }
5542a1be4b3SMarc-André Lureau }
5552a1be4b3SMarc-André Lureau 
object_initialize_with_type(Object * obj,size_t size,TypeImpl * type)556e27a9595SMasahiro Yamada static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
5572f28d2ffSAnthony Liguori {
558ac451033SIgor Mitsyanko     type_initialize(type);
559aca59af6SIgor Mitsyanko 
560719a3077SMarkus Armbruster     g_assert(type->instance_size >= sizeof(Object));
5612f28d2ffSAnthony Liguori     g_assert(type->abstract == false);
562719a3077SMarkus Armbruster     g_assert(size >= type->instance_size);
5632f28d2ffSAnthony Liguori 
5642f28d2ffSAnthony Liguori     memset(obj, 0, type->instance_size);
5652f28d2ffSAnthony Liguori     obj->class = type->class;
566764b6312SPaolo Bonzini     object_ref(obj);
5672a1be4b3SMarc-André Lureau     object_class_property_init_all(obj);
568b604a854SPavel Fedin     obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
569b604a854SPavel Fedin                                             NULL, object_property_free);
5702f28d2ffSAnthony Liguori     object_init_with_type(obj, type);
5718231c2ddSEduardo Habkost     object_post_init_with_type(obj, type);
5722f28d2ffSAnthony Liguori }
5732f28d2ffSAnthony Liguori 
object_initialize(void * data,size_t size,const char * typename)574213f0c4fSAndreas Färber void object_initialize(void *data, size_t size, const char *typename)
5752f28d2ffSAnthony Liguori {
5762f28d2ffSAnthony Liguori     TypeImpl *type = type_get_by_name(typename);
5772f28d2ffSAnthony Liguori 
57864f7aeceSGerd Hoffmann #ifdef CONFIG_MODULES
57964f7aeceSGerd Hoffmann     if (!type) {
580c551fb0bSClaudio Fontana         int rv = module_load_qom(typename, &error_fatal);
581c551fb0bSClaudio Fontana         if (rv > 0) {
58264f7aeceSGerd Hoffmann             type = type_get_by_name(typename);
583c551fb0bSClaudio Fontana         } else {
584c551fb0bSClaudio Fontana             error_report("missing object type '%s'", typename);
585c551fb0bSClaudio Fontana             exit(1);
586c551fb0bSClaudio Fontana         }
58764f7aeceSGerd Hoffmann     }
58864f7aeceSGerd Hoffmann #endif
589e02bdf1cSPhilippe Mathieu-Daudé     if (!type) {
590e02bdf1cSPhilippe Mathieu-Daudé         error_report("missing object type '%s'", typename);
591e02bdf1cSPhilippe Mathieu-Daudé         abort();
592e02bdf1cSPhilippe Mathieu-Daudé     }
593e02bdf1cSPhilippe Mathieu-Daudé 
5945b9237f6SAndreas Färber     object_initialize_with_type(data, size, type);
5952f28d2ffSAnthony Liguori }
5962f28d2ffSAnthony Liguori 
object_initialize_child_with_props(Object * parentobj,const char * propname,void * childobj,size_t size,const char * type,Error ** errp,...)5976fd5bef1SMarkus Armbruster bool object_initialize_child_with_props(Object *parentobj,
5989fc7fc4dSMarkus Armbruster                                         const char *propname,
5996fd5bef1SMarkus Armbruster                                         void *childobj, size_t size,
6006fd5bef1SMarkus Armbruster                                         const char *type,
6010210b39dSThomas Huth                                         Error **errp, ...)
6020210b39dSThomas Huth {
6030210b39dSThomas Huth     va_list vargs;
6046fd5bef1SMarkus Armbruster     bool ok;
6050210b39dSThomas Huth 
6060210b39dSThomas Huth     va_start(vargs, errp);
6076fd5bef1SMarkus Armbruster     ok = object_initialize_child_with_propsv(parentobj, propname,
6086fd5bef1SMarkus Armbruster                                              childobj, size, type, errp,
6096fd5bef1SMarkus Armbruster                                              vargs);
6100210b39dSThomas Huth     va_end(vargs);
6116fd5bef1SMarkus Armbruster     return ok;
6120210b39dSThomas Huth }
6130210b39dSThomas Huth 
object_initialize_child_with_propsv(Object * parentobj,const char * propname,void * childobj,size_t size,const char * type,Error ** errp,va_list vargs)6146fd5bef1SMarkus Armbruster bool object_initialize_child_with_propsv(Object *parentobj,
6159fc7fc4dSMarkus Armbruster                                          const char *propname,
6166fd5bef1SMarkus Armbruster                                          void *childobj, size_t size,
6176fd5bef1SMarkus Armbruster                                          const char *type,
6180210b39dSThomas Huth                                          Error **errp, va_list vargs)
6190210b39dSThomas Huth {
6206fd5bef1SMarkus Armbruster     bool ok = false;
6210210b39dSThomas Huth     Object *obj;
6223650b2deSMarc-André Lureau     UserCreatable *uc;
6230210b39dSThomas Huth 
6240210b39dSThomas Huth     object_initialize(childobj, size, type);
6250210b39dSThomas Huth     obj = OBJECT(childobj);
6260210b39dSThomas Huth 
627b783f54dSMarkus Armbruster     if (!object_set_propv(obj, errp, vargs)) {
6280210b39dSThomas Huth         goto out;
6290210b39dSThomas Huth     }
6300210b39dSThomas Huth 
631d2623129SMarkus Armbruster     object_property_add_child(parentobj, propname, obj);
6320210b39dSThomas Huth 
6333650b2deSMarc-André Lureau     uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
6343650b2deSMarc-André Lureau     if (uc) {
635992861fbSMarkus Armbruster         if (!user_creatable_complete(uc, errp)) {
6360210b39dSThomas Huth             object_unparent(obj);
6370210b39dSThomas Huth             goto out;
6380210b39dSThomas Huth         }
6390210b39dSThomas Huth     }
6400210b39dSThomas Huth 
6416fd5bef1SMarkus Armbruster     ok = true;
6426fd5bef1SMarkus Armbruster 
643975ac455SMarkus Armbruster out:
6440210b39dSThomas Huth     /*
645975ac455SMarkus Armbruster      * We want @obj's reference to be 1 on success, 0 on failure.
646975ac455SMarkus Armbruster      * On success, it's 2: one taken by object_initialize(), and one
647975ac455SMarkus Armbruster      * by object_property_add_child().
648975ac455SMarkus Armbruster      * On failure in object_initialize() or earlier, it's 1.
649975ac455SMarkus Armbruster      * On failure afterwards, it's also 1: object_unparent() releases
650975ac455SMarkus Armbruster      * the reference taken by object_property_add_child().
6510210b39dSThomas Huth      */
6520210b39dSThomas Huth     object_unref(obj);
6536fd5bef1SMarkus Armbruster     return ok;
6540210b39dSThomas Huth }
6550210b39dSThomas Huth 
object_initialize_child_internal(Object * parent,const char * propname,void * child,size_t size,const char * type)6569fc7fc4dSMarkus Armbruster void object_initialize_child_internal(Object *parent,
6579fc7fc4dSMarkus Armbruster                                       const char *propname,
6589fc7fc4dSMarkus Armbruster                                       void *child, size_t size,
6599fc7fc4dSMarkus Armbruster                                       const char *type)
6609fc7fc4dSMarkus Armbruster {
6619fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(parent, propname, child, size, type,
6629fc7fc4dSMarkus Armbruster                                        &error_abort, NULL);
6639fc7fc4dSMarkus Armbruster }
6649fc7fc4dSMarkus Armbruster 
object_property_is_child(ObjectProperty * prop)6655d9d3f47SAndreas Färber static inline bool object_property_is_child(ObjectProperty *prop)
6665d9d3f47SAndreas Färber {
6675d9d3f47SAndreas Färber     return strstart(prop->type, "child<", NULL);
6685d9d3f47SAndreas Färber }
6695d9d3f47SAndreas Färber 
object_property_del_all(Object * obj)67057c9fafeSAnthony Liguori static void object_property_del_all(Object *obj)
67157c9fafeSAnthony Liguori {
6729859faccSMarc-André Lureau     g_autoptr(GHashTable) done = g_hash_table_new(NULL, NULL);
673b604a854SPavel Fedin     ObjectProperty *prop;
6749859faccSMarc-André Lureau     ObjectPropertyIterator iter;
675b604a854SPavel Fedin     bool released;
67657c9fafeSAnthony Liguori 
677b604a854SPavel Fedin     do {
678b604a854SPavel Fedin         released = false;
6799859faccSMarc-André Lureau         object_property_iter_init(&iter, obj);
6809859faccSMarc-André Lureau         while ((prop = object_property_iter_next(&iter)) != NULL) {
6819859faccSMarc-André Lureau             if (g_hash_table_add(done, prop)) {
68257c9fafeSAnthony Liguori                 if (prop->release) {
68357c9fafeSAnthony Liguori                     prop->release(obj, prop->name, prop->opaque);
684b604a854SPavel Fedin                     released = true;
685b604a854SPavel Fedin                     break;
68657c9fafeSAnthony Liguori                 }
6879859faccSMarc-André Lureau             }
688b604a854SPavel Fedin         }
689b604a854SPavel Fedin     } while (released);
69057c9fafeSAnthony Liguori 
691b604a854SPavel Fedin     g_hash_table_unref(obj->properties);
69257c9fafeSAnthony Liguori }
69357c9fafeSAnthony Liguori 
object_property_del_child(Object * obj,Object * child)694f73a32a5SMarkus Armbruster static void object_property_del_child(Object *obj, Object *child)
69557c9fafeSAnthony Liguori {
69657c9fafeSAnthony Liguori     ObjectProperty *prop;
697b604a854SPavel Fedin     GHashTableIter iter;
698b604a854SPavel Fedin     gpointer key, value;
69957c9fafeSAnthony Liguori 
700b604a854SPavel Fedin     g_hash_table_iter_init(&iter, obj->properties);
701b604a854SPavel Fedin     while (g_hash_table_iter_next(&iter, &key, &value)) {
702b604a854SPavel Fedin         prop = value;
7035d9d3f47SAndreas Färber         if (object_property_is_child(prop) && prop->opaque == child) {
704b604a854SPavel Fedin             if (prop->release) {
705b604a854SPavel Fedin                 prop->release(obj, prop->name, prop->opaque);
706b604a854SPavel Fedin                 prop->release = NULL;
707b604a854SPavel Fedin             }
708b604a854SPavel Fedin             break;
709b604a854SPavel Fedin         }
710b604a854SPavel Fedin     }
711b604a854SPavel Fedin     g_hash_table_iter_init(&iter, obj->properties);
712b604a854SPavel Fedin     while (g_hash_table_iter_next(&iter, &key, &value)) {
713b604a854SPavel Fedin         prop = value;
714b604a854SPavel Fedin         if (object_property_is_child(prop) && prop->opaque == child) {
715b604a854SPavel Fedin             g_hash_table_iter_remove(&iter);
7166c1fdcf9SPaolo Bonzini             break;
71757c9fafeSAnthony Liguori         }
71857c9fafeSAnthony Liguori     }
71957c9fafeSAnthony Liguori }
72057c9fafeSAnthony Liguori 
object_unparent(Object * obj)72157c9fafeSAnthony Liguori void object_unparent(Object *obj)
72257c9fafeSAnthony Liguori {
723e998fa8dSMichael S. Tsirkin     if (obj->parent) {
724f73a32a5SMarkus Armbruster         object_property_del_child(obj->parent, obj);
725e998fa8dSMichael S. Tsirkin     }
72657c9fafeSAnthony Liguori }
72757c9fafeSAnthony Liguori 
object_deinit(Object * obj,TypeImpl * type)7282f28d2ffSAnthony Liguori static void object_deinit(Object *obj, TypeImpl *type)
7292f28d2ffSAnthony Liguori {
7302f28d2ffSAnthony Liguori     if (type->instance_finalize) {
7312f28d2ffSAnthony Liguori         type->instance_finalize(obj);
7322f28d2ffSAnthony Liguori     }
7332f28d2ffSAnthony Liguori 
7342f28d2ffSAnthony Liguori     if (type_has_parent(type)) {
7352f28d2ffSAnthony Liguori         object_deinit(obj, type_get_parent(type));
7362f28d2ffSAnthony Liguori     }
7372f28d2ffSAnthony Liguori }
7382f28d2ffSAnthony Liguori 
object_finalize(void * data)739339c2708SPaolo Bonzini static void object_finalize(void *data)
7402f28d2ffSAnthony Liguori {
7412f28d2ffSAnthony Liguori     Object *obj = data;
7422f28d2ffSAnthony Liguori     TypeImpl *ti = obj->class->type;
7432f28d2ffSAnthony Liguori 
74457c9fafeSAnthony Liguori     object_property_del_all(obj);
74576a6e1ccSPaolo Bonzini     object_deinit(obj, ti);
746db85b575SAnthony Liguori 
747719a3077SMarkus Armbruster     g_assert(obj->ref == 0);
74863f957acSEduardo Habkost     g_assert(obj->parent == NULL);
749fde9bf44SPaolo Bonzini     if (obj->free) {
750fde9bf44SPaolo Bonzini         obj->free(obj);
751fde9bf44SPaolo Bonzini     }
7522f28d2ffSAnthony Liguori }
7532f28d2ffSAnthony Liguori 
7544c880f36SRichard Henderson /* Find the minimum alignment guaranteed by the system malloc. */
7554c880f36SRichard Henderson #if __STDC_VERSION__ >= 201112L
7563a2e982dSDoug Evans typedef max_align_t qemu_max_align_t;
7574c880f36SRichard Henderson #else
7584c880f36SRichard Henderson typedef union {
7594c880f36SRichard Henderson     long l;
7604c880f36SRichard Henderson     void *p;
7614c880f36SRichard Henderson     double d;
7624c880f36SRichard Henderson     long double ld;
7634c880f36SRichard Henderson } qemu_max_align_t;
7644c880f36SRichard Henderson #endif
7654c880f36SRichard Henderson 
object_new_with_type(Type type)76663f7b10bSMarc-André Lureau static Object *object_new_with_type(Type type)
7672f28d2ffSAnthony Liguori {
7682f28d2ffSAnthony Liguori     Object *obj;
7694c880f36SRichard Henderson     size_t size, align;
7704c880f36SRichard Henderson     void (*obj_free)(void *);
7712f28d2ffSAnthony Liguori 
7722f28d2ffSAnthony Liguori     g_assert(type != NULL);
773ac451033SIgor Mitsyanko     type_initialize(type);
7742f28d2ffSAnthony Liguori 
7754c880f36SRichard Henderson     size = type->instance_size;
7764c880f36SRichard Henderson     align = type->instance_align;
7774c880f36SRichard Henderson 
7784c880f36SRichard Henderson     /*
7794c880f36SRichard Henderson      * Do not use qemu_memalign unless required.  Depending on the
7804c880f36SRichard Henderson      * implementation, extra alignment implies extra overhead.
7814c880f36SRichard Henderson      */
7824c880f36SRichard Henderson     if (likely(align <= __alignof__(qemu_max_align_t))) {
7834c880f36SRichard Henderson         obj = g_malloc(size);
7844c880f36SRichard Henderson         obj_free = g_free;
7854c880f36SRichard Henderson     } else {
7864c880f36SRichard Henderson         obj = qemu_memalign(align, size);
7874c880f36SRichard Henderson         obj_free = qemu_vfree;
7884c880f36SRichard Henderson     }
7894c880f36SRichard Henderson 
7904c880f36SRichard Henderson     object_initialize_with_type(obj, size, type);
7914c880f36SRichard Henderson     obj->free = obj_free;
7922f28d2ffSAnthony Liguori 
7932f28d2ffSAnthony Liguori     return obj;
7942f28d2ffSAnthony Liguori }
7952f28d2ffSAnthony Liguori 
object_new_with_class(ObjectClass * klass)7963c75e12eSPaolo Bonzini Object *object_new_with_class(ObjectClass *klass)
7973c75e12eSPaolo Bonzini {
7983c75e12eSPaolo Bonzini     return object_new_with_type(klass->type);
7993c75e12eSPaolo Bonzini }
8003c75e12eSPaolo Bonzini 
object_new(const char * typename)8012f28d2ffSAnthony Liguori Object *object_new(const char *typename)
8022f28d2ffSAnthony Liguori {
8032f28d2ffSAnthony Liguori     TypeImpl *ti = type_get_by_name(typename);
8042f28d2ffSAnthony Liguori 
8052f28d2ffSAnthony Liguori     return object_new_with_type(ti);
8062f28d2ffSAnthony Liguori }
8072f28d2ffSAnthony Liguori 
808a31bdae5SDaniel P. Berrange 
object_new_with_props(const char * typename,Object * parent,const char * id,Error ** errp,...)809a31bdae5SDaniel P. Berrange Object *object_new_with_props(const char *typename,
810a31bdae5SDaniel P. Berrange                               Object *parent,
811a31bdae5SDaniel P. Berrange                               const char *id,
812a31bdae5SDaniel P. Berrange                               Error **errp,
813a31bdae5SDaniel P. Berrange                               ...)
814a31bdae5SDaniel P. Berrange {
815a31bdae5SDaniel P. Berrange     va_list vargs;
816a31bdae5SDaniel P. Berrange     Object *obj;
817a31bdae5SDaniel P. Berrange 
818a31bdae5SDaniel P. Berrange     va_start(vargs, errp);
819a31bdae5SDaniel P. Berrange     obj = object_new_with_propv(typename, parent, id, errp, vargs);
820a31bdae5SDaniel P. Berrange     va_end(vargs);
821a31bdae5SDaniel P. Berrange 
822a31bdae5SDaniel P. Berrange     return obj;
823a31bdae5SDaniel P. Berrange }
824a31bdae5SDaniel P. Berrange 
825a31bdae5SDaniel P. Berrange 
object_new_with_propv(const char * typename,Object * parent,const char * id,Error ** errp,va_list vargs)826a31bdae5SDaniel P. Berrange Object *object_new_with_propv(const char *typename,
827a31bdae5SDaniel P. Berrange                               Object *parent,
828a31bdae5SDaniel P. Berrange                               const char *id,
829a31bdae5SDaniel P. Berrange                               Error **errp,
830a31bdae5SDaniel P. Berrange                               va_list vargs)
831a31bdae5SDaniel P. Berrange {
832a31bdae5SDaniel P. Berrange     Object *obj;
833a31bdae5SDaniel P. Berrange     ObjectClass *klass;
8343650b2deSMarc-André Lureau     UserCreatable *uc;
835a31bdae5SDaniel P. Berrange 
836a31bdae5SDaniel P. Berrange     klass = object_class_by_name(typename);
837a31bdae5SDaniel P. Berrange     if (!klass) {
838a31bdae5SDaniel P. Berrange         error_setg(errp, "invalid object type: %s", typename);
839a31bdae5SDaniel P. Berrange         return NULL;
840a31bdae5SDaniel P. Berrange     }
841a31bdae5SDaniel P. Berrange 
842a31bdae5SDaniel P. Berrange     if (object_class_is_abstract(klass)) {
843a31bdae5SDaniel P. Berrange         error_setg(errp, "object type '%s' is abstract", typename);
844a31bdae5SDaniel P. Berrange         return NULL;
845a31bdae5SDaniel P. Berrange     }
84666e1155aSWei Yang     obj = object_new_with_type(klass->type);
847a31bdae5SDaniel P. Berrange 
848b783f54dSMarkus Armbruster     if (!object_set_propv(obj, errp, vargs)) {
849a31bdae5SDaniel P. Berrange         goto error;
850a31bdae5SDaniel P. Berrange     }
851a31bdae5SDaniel P. Berrange 
8526134d752SDaniel P. Berrangé     if (id != NULL) {
853d2623129SMarkus Armbruster         object_property_add_child(parent, id, obj);
8546134d752SDaniel P. Berrangé     }
855a31bdae5SDaniel P. Berrange 
8563650b2deSMarc-André Lureau     uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
8573650b2deSMarc-André Lureau     if (uc) {
858992861fbSMarkus Armbruster         if (!user_creatable_complete(uc, errp)) {
8596134d752SDaniel P. Berrangé             if (id != NULL) {
860a31bdae5SDaniel P. Berrange                 object_unparent(obj);
8616134d752SDaniel P. Berrangé             }
862a31bdae5SDaniel P. Berrange             goto error;
863a31bdae5SDaniel P. Berrange         }
864a31bdae5SDaniel P. Berrange     }
865a31bdae5SDaniel P. Berrange 
866688ffbb4SPhilippe Mathieu-Daudé     object_unref(obj);
867a31bdae5SDaniel P. Berrange     return obj;
868a31bdae5SDaniel P. Berrange 
869a31bdae5SDaniel P. Berrange  error:
870a31bdae5SDaniel P. Berrange     object_unref(obj);
871a31bdae5SDaniel P. Berrange     return NULL;
872a31bdae5SDaniel P. Berrange }
873a31bdae5SDaniel P. Berrange 
874a31bdae5SDaniel P. Berrange 
object_set_props(Object * obj,Error ** errp,...)875b783f54dSMarkus Armbruster bool object_set_props(Object *obj,
876a31bdae5SDaniel P. Berrange                      Error **errp,
877a31bdae5SDaniel P. Berrange                      ...)
878a31bdae5SDaniel P. Berrange {
879a31bdae5SDaniel P. Berrange     va_list vargs;
880b783f54dSMarkus Armbruster     bool ret;
881a31bdae5SDaniel P. Berrange 
882a31bdae5SDaniel P. Berrange     va_start(vargs, errp);
883a31bdae5SDaniel P. Berrange     ret = object_set_propv(obj, errp, vargs);
884a31bdae5SDaniel P. Berrange     va_end(vargs);
885a31bdae5SDaniel P. Berrange 
886a31bdae5SDaniel P. Berrange     return ret;
887a31bdae5SDaniel P. Berrange }
888a31bdae5SDaniel P. Berrange 
889a31bdae5SDaniel P. Berrange 
object_set_propv(Object * obj,Error ** errp,va_list vargs)890b783f54dSMarkus Armbruster bool object_set_propv(Object *obj,
891a31bdae5SDaniel P. Berrange                      Error **errp,
892a31bdae5SDaniel P. Berrange                      va_list vargs)
893a31bdae5SDaniel P. Berrange {
894a31bdae5SDaniel P. Berrange     const char *propname;
895a31bdae5SDaniel P. Berrange 
896a31bdae5SDaniel P. Berrange     propname = va_arg(vargs, char *);
897a31bdae5SDaniel P. Berrange     while (propname != NULL) {
898a31bdae5SDaniel P. Berrange         const char *value = va_arg(vargs, char *);
899a31bdae5SDaniel P. Berrange 
900a31bdae5SDaniel P. Berrange         g_assert(value != NULL);
901668f62ecSMarkus Armbruster         if (!object_property_parse(obj, propname, value, errp)) {
902b783f54dSMarkus Armbruster             return false;
903a31bdae5SDaniel P. Berrange         }
904a31bdae5SDaniel P. Berrange         propname = va_arg(vargs, char *);
905a31bdae5SDaniel P. Berrange     }
906a31bdae5SDaniel P. Berrange 
907b783f54dSMarkus Armbruster     return true;
908a31bdae5SDaniel P. Berrange }
909a31bdae5SDaniel P. Berrange 
910a31bdae5SDaniel P. Berrange 
object_dynamic_cast(Object * obj,const char * typename)9112f28d2ffSAnthony Liguori Object *object_dynamic_cast(Object *obj, const char *typename)
9122f28d2ffSAnthony Liguori {
913b7f43fe4SPaolo Bonzini     if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
914acc4af3fSPaolo Bonzini         return obj;
915acc4af3fSPaolo Bonzini     }
916acc4af3fSPaolo Bonzini 
9172f28d2ffSAnthony Liguori     return NULL;
9182f28d2ffSAnthony Liguori }
9192f28d2ffSAnthony Liguori 
object_dynamic_cast_assert(Object * obj,const char * typename,const char * file,int line,const char * func)920be17f18bSPaolo Bonzini Object *object_dynamic_cast_assert(Object *obj, const char *typename,
921be17f18bSPaolo Bonzini                                    const char *file, int line, const char *func)
9222f28d2ffSAnthony Liguori {
923fa131d94SPaolo Bonzini     trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
924fa131d94SPaolo Bonzini                                      typename, file, line, func);
925fa131d94SPaolo Bonzini 
9263556c233SPaolo Bonzini #ifdef CONFIG_QOM_CAST_DEBUG
92703587328SAnthony Liguori     int i;
92803587328SAnthony Liguori     Object *inst;
92903587328SAnthony Liguori 
93095916abcSPeter Crosthwaite     for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
931d73415a3SStefan Hajnoczi         if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) {
93203587328SAnthony Liguori             goto out;
93303587328SAnthony Liguori         }
93403587328SAnthony Liguori     }
93503587328SAnthony Liguori 
93603587328SAnthony Liguori     inst = object_dynamic_cast(obj, typename);
9372f28d2ffSAnthony Liguori 
938b7f43fe4SPaolo Bonzini     if (!inst && obj) {
939be17f18bSPaolo Bonzini         fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
940be17f18bSPaolo Bonzini                 file, line, func, obj, typename);
9412f28d2ffSAnthony Liguori         abort();
9422f28d2ffSAnthony Liguori     }
9432f28d2ffSAnthony Liguori 
9443556c233SPaolo Bonzini     assert(obj == inst);
94503587328SAnthony Liguori 
94695916abcSPeter Crosthwaite     if (obj && obj == inst) {
94703587328SAnthony Liguori         for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
948d73415a3SStefan Hajnoczi             qatomic_set(&obj->class->object_cast_cache[i - 1],
949d73415a3SStefan Hajnoczi                        qatomic_read(&obj->class->object_cast_cache[i]));
95003587328SAnthony Liguori         }
951d73415a3SStefan Hajnoczi         qatomic_set(&obj->class->object_cast_cache[i - 1], typename);
95203587328SAnthony Liguori     }
95303587328SAnthony Liguori 
95403587328SAnthony Liguori out:
9553556c233SPaolo Bonzini #endif
9563556c233SPaolo Bonzini     return obj;
9572f28d2ffSAnthony Liguori }
9582f28d2ffSAnthony Liguori 
object_class_dynamic_cast(ObjectClass * class,const char * typename)9592f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast(ObjectClass *class,
9602f28d2ffSAnthony Liguori                                        const char *typename)
9612f28d2ffSAnthony Liguori {
96233e95c63SAnthony Liguori     ObjectClass *ret = NULL;
963bf0fda34SPaolo Bonzini     TypeImpl *target_type;
964bf0fda34SPaolo Bonzini     TypeImpl *type;
9652f28d2ffSAnthony Liguori 
966bf0fda34SPaolo Bonzini     if (!class) {
967bf0fda34SPaolo Bonzini         return NULL;
968bf0fda34SPaolo Bonzini     }
969bf0fda34SPaolo Bonzini 
970793c96b5SPaolo Bonzini     /* A simple fast path that can trigger a lot for leaf classes.  */
971bf0fda34SPaolo Bonzini     type = class->type;
972793c96b5SPaolo Bonzini     if (type->name == typename) {
973793c96b5SPaolo Bonzini         return class;
974793c96b5SPaolo Bonzini     }
975793c96b5SPaolo Bonzini 
976bf0fda34SPaolo Bonzini     target_type = type_get_by_name(typename);
9779ab880b3SAlexander Graf     if (!target_type) {
9789ab880b3SAlexander Graf         /* target class type unknown, so fail the cast */
9799ab880b3SAlexander Graf         return NULL;
9809ab880b3SAlexander Graf     }
9819ab880b3SAlexander Graf 
98200e2ceaeSPeter Crosthwaite     if (type->class->interfaces &&
98300e2ceaeSPeter Crosthwaite             type_is_ancestor(target_type, type_interface)) {
98433e95c63SAnthony Liguori         int found = 0;
98533e95c63SAnthony Liguori         GSList *i;
98633e95c63SAnthony Liguori 
98733e95c63SAnthony Liguori         for (i = class->interfaces; i; i = i->next) {
98833e95c63SAnthony Liguori             ObjectClass *target_class = i->data;
98933e95c63SAnthony Liguori 
99033e95c63SAnthony Liguori             if (type_is_ancestor(target_class->type, target_type)) {
99133e95c63SAnthony Liguori                 ret = target_class;
99233e95c63SAnthony Liguori                 found++;
99333e95c63SAnthony Liguori             }
9942f28d2ffSAnthony Liguori          }
9952f28d2ffSAnthony Liguori 
99633e95c63SAnthony Liguori         /* The match was ambiguous, don't allow a cast */
99733e95c63SAnthony Liguori         if (found > 1) {
99833e95c63SAnthony Liguori             ret = NULL;
99933e95c63SAnthony Liguori         }
100033e95c63SAnthony Liguori     } else if (type_is_ancestor(type, target_type)) {
100133e95c63SAnthony Liguori         ret = class;
10022f28d2ffSAnthony Liguori     }
10032f28d2ffSAnthony Liguori 
100433e95c63SAnthony Liguori     return ret;
10052f28d2ffSAnthony Liguori }
10062f28d2ffSAnthony Liguori 
object_class_dynamic_cast_assert(ObjectClass * class,const char * typename,const char * file,int line,const char * func)10072f28d2ffSAnthony Liguori ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
1008be17f18bSPaolo Bonzini                                               const char *typename,
1009be17f18bSPaolo Bonzini                                               const char *file, int line,
1010be17f18bSPaolo Bonzini                                               const char *func)
10112f28d2ffSAnthony Liguori {
1012fa131d94SPaolo Bonzini     ObjectClass *ret;
10132f28d2ffSAnthony Liguori 
1014fa131d94SPaolo Bonzini     trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
1015fa131d94SPaolo Bonzini                                            typename, file, line, func);
1016fa131d94SPaolo Bonzini 
101703587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG
101803587328SAnthony Liguori     int i;
101903587328SAnthony Liguori 
10209d6a3d58SPeter Crosthwaite     for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
1021d73415a3SStefan Hajnoczi         if (qatomic_read(&class->class_cast_cache[i]) == typename) {
102203587328SAnthony Liguori             ret = class;
102303587328SAnthony Liguori             goto out;
102403587328SAnthony Liguori         }
102503587328SAnthony Liguori     }
102603587328SAnthony Liguori #else
10279d6a3d58SPeter Crosthwaite     if (!class || !class->interfaces) {
10283556c233SPaolo Bonzini         return class;
10293556c233SPaolo Bonzini     }
10303556c233SPaolo Bonzini #endif
10313556c233SPaolo Bonzini 
1032fa131d94SPaolo Bonzini     ret = object_class_dynamic_cast(class, typename);
1033bf0fda34SPaolo Bonzini     if (!ret && class) {
1034be17f18bSPaolo Bonzini         fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
1035be17f18bSPaolo Bonzini                 file, line, func, class, typename);
10362f28d2ffSAnthony Liguori         abort();
10372f28d2ffSAnthony Liguori     }
10382f28d2ffSAnthony Liguori 
103903587328SAnthony Liguori #ifdef CONFIG_QOM_CAST_DEBUG
10409d6a3d58SPeter Crosthwaite     if (class && ret == class) {
104103587328SAnthony Liguori         for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
1042d73415a3SStefan Hajnoczi             qatomic_set(&class->class_cast_cache[i - 1],
1043d73415a3SStefan Hajnoczi                        qatomic_read(&class->class_cast_cache[i]));
104403587328SAnthony Liguori         }
1045d73415a3SStefan Hajnoczi         qatomic_set(&class->class_cast_cache[i - 1], typename);
104603587328SAnthony Liguori     }
104703587328SAnthony Liguori out:
104803587328SAnthony Liguori #endif
10492f28d2ffSAnthony Liguori     return ret;
10502f28d2ffSAnthony Liguori }
10512f28d2ffSAnthony Liguori 
object_get_typename(const Object * obj)10528f5d58efSIgor Mammedov const char *object_get_typename(const Object *obj)
10532f28d2ffSAnthony Liguori {
10542f28d2ffSAnthony Liguori     return obj->class->type->name;
10552f28d2ffSAnthony Liguori }
10562f28d2ffSAnthony Liguori 
object_get_class(Object * obj)10572f28d2ffSAnthony Liguori ObjectClass *object_get_class(Object *obj)
10582f28d2ffSAnthony Liguori {
10592f28d2ffSAnthony Liguori     return obj->class;
10602f28d2ffSAnthony Liguori }
10612f28d2ffSAnthony Liguori 
object_class_is_abstract(ObjectClass * klass)106217862378SAndreas Färber bool object_class_is_abstract(ObjectClass *klass)
106317862378SAndreas Färber {
106417862378SAndreas Färber     return klass->type->abstract;
106517862378SAndreas Färber }
106617862378SAndreas Färber 
object_class_get_name(ObjectClass * klass)10672f28d2ffSAnthony Liguori const char *object_class_get_name(ObjectClass *klass)
10682f28d2ffSAnthony Liguori {
10692f28d2ffSAnthony Liguori     return klass->type->name;
10702f28d2ffSAnthony Liguori }
10712f28d2ffSAnthony Liguori 
object_class_by_name(const char * typename)10722f28d2ffSAnthony Liguori ObjectClass *object_class_by_name(const char *typename)
10732f28d2ffSAnthony Liguori {
10742f28d2ffSAnthony Liguori     TypeImpl *type = type_get_by_name(typename);
10752f28d2ffSAnthony Liguori 
10762f28d2ffSAnthony Liguori     if (!type) {
10772f28d2ffSAnthony Liguori         return NULL;
10782f28d2ffSAnthony Liguori     }
10792f28d2ffSAnthony Liguori 
1080ac451033SIgor Mitsyanko     type_initialize(type);
10812f28d2ffSAnthony Liguori 
10822f28d2ffSAnthony Liguori     return type->class;
10832f28d2ffSAnthony Liguori }
10842f28d2ffSAnthony Liguori 
module_object_class_by_name(const char * typename)10850f8198f1SGerd Hoffmann ObjectClass *module_object_class_by_name(const char *typename)
10860f8198f1SGerd Hoffmann {
10870f8198f1SGerd Hoffmann     ObjectClass *oc;
10880f8198f1SGerd Hoffmann 
10890f8198f1SGerd Hoffmann     oc = object_class_by_name(typename);
10900f8198f1SGerd Hoffmann #ifdef CONFIG_MODULES
10910f8198f1SGerd Hoffmann     if (!oc) {
1092c551fb0bSClaudio Fontana         Error *local_err = NULL;
1093c551fb0bSClaudio Fontana         int rv = module_load_qom(typename, &local_err);
1094c551fb0bSClaudio Fontana         if (rv > 0) {
10950f8198f1SGerd Hoffmann             oc = object_class_by_name(typename);
1096c551fb0bSClaudio Fontana         } else if (rv < 0) {
1097c551fb0bSClaudio Fontana             error_report_err(local_err);
1098c551fb0bSClaudio Fontana         }
10990f8198f1SGerd Hoffmann     }
11000f8198f1SGerd Hoffmann #endif
11010f8198f1SGerd Hoffmann     return oc;
11020f8198f1SGerd Hoffmann }
11030f8198f1SGerd Hoffmann 
object_class_get_parent(ObjectClass * class)1104e7cce67fSPaolo Bonzini ObjectClass *object_class_get_parent(ObjectClass *class)
1105e7cce67fSPaolo Bonzini {
1106e7cce67fSPaolo Bonzini     TypeImpl *type = type_get_parent(class->type);
1107e7cce67fSPaolo Bonzini 
1108e7cce67fSPaolo Bonzini     if (!type) {
1109e7cce67fSPaolo Bonzini         return NULL;
1110e7cce67fSPaolo Bonzini     }
1111e7cce67fSPaolo Bonzini 
1112e7cce67fSPaolo Bonzini     type_initialize(type);
1113e7cce67fSPaolo Bonzini 
1114e7cce67fSPaolo Bonzini     return type->class;
1115e7cce67fSPaolo Bonzini }
1116e7cce67fSPaolo Bonzini 
11172f28d2ffSAnthony Liguori typedef struct OCFData
11182f28d2ffSAnthony Liguori {
11192f28d2ffSAnthony Liguori     void (*fn)(ObjectClass *klass, void *opaque);
112093c511a1SAnthony Liguori     const char *implements_type;
112193c511a1SAnthony Liguori     bool include_abstract;
11222f28d2ffSAnthony Liguori     void *opaque;
11232f28d2ffSAnthony Liguori } OCFData;
11242f28d2ffSAnthony Liguori 
object_class_foreach_tramp(gpointer key,gpointer value,gpointer opaque)11252f28d2ffSAnthony Liguori static void object_class_foreach_tramp(gpointer key, gpointer value,
11262f28d2ffSAnthony Liguori                                        gpointer opaque)
11272f28d2ffSAnthony Liguori {
11282f28d2ffSAnthony Liguori     OCFData *data = opaque;
11292f28d2ffSAnthony Liguori     TypeImpl *type = value;
113093c511a1SAnthony Liguori     ObjectClass *k;
11312f28d2ffSAnthony Liguori 
1132ac451033SIgor Mitsyanko     type_initialize(type);
113393c511a1SAnthony Liguori     k = type->class;
11342f28d2ffSAnthony Liguori 
113593c511a1SAnthony Liguori     if (!data->include_abstract && type->abstract) {
113693c511a1SAnthony Liguori         return;
113793c511a1SAnthony Liguori     }
113893c511a1SAnthony Liguori 
113993c511a1SAnthony Liguori     if (data->implements_type &&
114093c511a1SAnthony Liguori         !object_class_dynamic_cast(k, data->implements_type)) {
114193c511a1SAnthony Liguori         return;
114293c511a1SAnthony Liguori     }
114393c511a1SAnthony Liguori 
114493c511a1SAnthony Liguori     data->fn(k, data->opaque);
11452f28d2ffSAnthony Liguori }
11462f28d2ffSAnthony Liguori 
object_class_foreach(void (* fn)(ObjectClass * klass,void * opaque),const char * implements_type,bool include_abstract,void * opaque)11472f28d2ffSAnthony Liguori void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
114893c511a1SAnthony Liguori                           const char *implements_type, bool include_abstract,
11492f28d2ffSAnthony Liguori                           void *opaque)
11502f28d2ffSAnthony Liguori {
115193c511a1SAnthony Liguori     OCFData data = { fn, implements_type, include_abstract, opaque };
11522f28d2ffSAnthony Liguori 
1153f54c19caSHervé Poussineau     enumerating_types = true;
11542f28d2ffSAnthony Liguori     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
1155f54c19caSHervé Poussineau     enumerating_types = false;
11562f28d2ffSAnthony Liguori }
115757c9fafeSAnthony Liguori 
do_object_child_foreach(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque,bool recurse)1158d714b8deSPeter Crosthwaite static int do_object_child_foreach(Object *obj,
1159d714b8deSPeter Crosthwaite                                    int (*fn)(Object *child, void *opaque),
1160d714b8deSPeter Crosthwaite                                    void *opaque, bool recurse)
116132efc535SPaolo Bonzini {
1162b604a854SPavel Fedin     GHashTableIter iter;
1163b604a854SPavel Fedin     ObjectProperty *prop;
116432efc535SPaolo Bonzini     int ret = 0;
116532efc535SPaolo Bonzini 
1166b604a854SPavel Fedin     g_hash_table_iter_init(&iter, obj->properties);
1167b604a854SPavel Fedin     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
116832efc535SPaolo Bonzini         if (object_property_is_child(prop)) {
1169d714b8deSPeter Crosthwaite             Object *child = prop->opaque;
1170d714b8deSPeter Crosthwaite 
1171d714b8deSPeter Crosthwaite             ret = fn(child, opaque);
117232efc535SPaolo Bonzini             if (ret != 0) {
117332efc535SPaolo Bonzini                 break;
117432efc535SPaolo Bonzini             }
1175d714b8deSPeter Crosthwaite             if (recurse) {
11764a39181dSCédric Le Goater                 ret = do_object_child_foreach(child, fn, opaque, true);
11774a39181dSCédric Le Goater                 if (ret != 0) {
11784a39181dSCédric Le Goater                     break;
11794a39181dSCédric Le Goater                 }
1180d714b8deSPeter Crosthwaite             }
118132efc535SPaolo Bonzini         }
118232efc535SPaolo Bonzini     }
118332efc535SPaolo Bonzini     return ret;
118432efc535SPaolo Bonzini }
118532efc535SPaolo Bonzini 
object_child_foreach(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque)1186d714b8deSPeter Crosthwaite int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
1187d714b8deSPeter Crosthwaite                          void *opaque)
1188d714b8deSPeter Crosthwaite {
1189d714b8deSPeter Crosthwaite     return do_object_child_foreach(obj, fn, opaque, false);
1190d714b8deSPeter Crosthwaite }
1191d714b8deSPeter Crosthwaite 
object_child_foreach_recursive(Object * obj,int (* fn)(Object * child,void * opaque),void * opaque)1192d714b8deSPeter Crosthwaite int object_child_foreach_recursive(Object *obj,
1193d714b8deSPeter Crosthwaite                                    int (*fn)(Object *child, void *opaque),
1194d714b8deSPeter Crosthwaite                                    void *opaque)
1195d714b8deSPeter Crosthwaite {
1196d714b8deSPeter Crosthwaite     return do_object_child_foreach(obj, fn, opaque, true);
1197d714b8deSPeter Crosthwaite }
1198d714b8deSPeter Crosthwaite 
object_class_get_list_tramp(ObjectClass * klass,void * opaque)1199418ba9e5SAndreas Färber static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
1200418ba9e5SAndreas Färber {
1201418ba9e5SAndreas Färber     GSList **list = opaque;
1202418ba9e5SAndreas Färber 
1203418ba9e5SAndreas Färber     *list = g_slist_prepend(*list, klass);
1204418ba9e5SAndreas Färber }
1205418ba9e5SAndreas Färber 
object_class_get_list(const char * implements_type,bool include_abstract)1206418ba9e5SAndreas Färber GSList *object_class_get_list(const char *implements_type,
1207418ba9e5SAndreas Färber                               bool include_abstract)
1208418ba9e5SAndreas Färber {
1209418ba9e5SAndreas Färber     GSList *list = NULL;
1210418ba9e5SAndreas Färber 
1211418ba9e5SAndreas Färber     object_class_foreach(object_class_get_list_tramp,
1212418ba9e5SAndreas Färber                          implements_type, include_abstract, &list);
1213418ba9e5SAndreas Färber     return list;
1214418ba9e5SAndreas Färber }
1215418ba9e5SAndreas Färber 
object_class_cmp(gconstpointer a,gconstpointer b)121647c66009SPaolo Bonzini static gint object_class_cmp(gconstpointer a, gconstpointer b)
121747c66009SPaolo Bonzini {
121847c66009SPaolo Bonzini     return strcasecmp(object_class_get_name((ObjectClass *)a),
121947c66009SPaolo Bonzini                       object_class_get_name((ObjectClass *)b));
122047c66009SPaolo Bonzini }
122147c66009SPaolo Bonzini 
object_class_get_list_sorted(const char * implements_type,bool include_abstract)122247c66009SPaolo Bonzini GSList *object_class_get_list_sorted(const char *implements_type,
122347c66009SPaolo Bonzini                                      bool include_abstract)
122447c66009SPaolo Bonzini {
122547c66009SPaolo Bonzini     return g_slist_sort(object_class_get_list(implements_type, include_abstract),
122647c66009SPaolo Bonzini                         object_class_cmp);
122747c66009SPaolo Bonzini }
122847c66009SPaolo Bonzini 
object_ref(void * objptr)1229c5a61e5aSDaniel P. Berrangé Object *object_ref(void *objptr)
123057c9fafeSAnthony Liguori {
1231c5a61e5aSDaniel P. Berrangé     Object *obj = OBJECT(objptr);
1232e3682878SMichael S. Tsirkin     uint32_t ref;
1233e3682878SMichael S. Tsirkin 
12348ffad850SPeter Crosthwaite     if (!obj) {
1235b77ade9bSMarc-André Lureau         return NULL;
12368ffad850SPeter Crosthwaite     }
1237e3682878SMichael S. Tsirkin     ref = qatomic_fetch_inc(&obj->ref);
1238e3682878SMichael S. Tsirkin     /* Assert waaay before the integer overflows */
1239e3682878SMichael S. Tsirkin     g_assert(ref < INT_MAX);
1240b77ade9bSMarc-André Lureau     return obj;
124157c9fafeSAnthony Liguori }
124257c9fafeSAnthony Liguori 
object_unref(void * objptr)1243c5a61e5aSDaniel P. Berrangé void object_unref(void *objptr)
124457c9fafeSAnthony Liguori {
1245c5a61e5aSDaniel P. Berrangé     Object *obj = OBJECT(objptr);
12468ffad850SPeter Crosthwaite     if (!obj) {
12478ffad850SPeter Crosthwaite         return;
12488ffad850SPeter Crosthwaite     }
1249719a3077SMarkus Armbruster     g_assert(obj->ref > 0);
125057c9fafeSAnthony Liguori 
125157c9fafeSAnthony Liguori     /* parent always holds a reference to its children */
1252d73415a3SStefan Hajnoczi     if (qatomic_fetch_dec(&obj->ref) == 1) {
125357c9fafeSAnthony Liguori         object_finalize(obj);
125457c9fafeSAnthony Liguori     }
125557c9fafeSAnthony Liguori }
125657c9fafeSAnthony Liguori 
1257db57fef1SEric Auger ObjectProperty *
object_property_try_add(Object * obj,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque,Error ** errp)1258d2623129SMarkus Armbruster object_property_try_add(Object *obj, const char *name, const char *type,
125957c9fafeSAnthony Liguori                         ObjectPropertyAccessor *get,
126057c9fafeSAnthony Liguori                         ObjectPropertyAccessor *set,
126157c9fafeSAnthony Liguori                         ObjectPropertyRelease *release,
126257c9fafeSAnthony Liguori                         void *opaque, Error **errp)
126357c9fafeSAnthony Liguori {
126454852b03SPeter Maydell     ObjectProperty *prop;
126533965904SPeter Crosthwaite     size_t name_len = strlen(name);
126633965904SPeter Crosthwaite 
126733965904SPeter Crosthwaite     if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
126833965904SPeter Crosthwaite         int i;
12691bf8b88fSAni Sinha         ObjectProperty *ret = NULL;
127033965904SPeter Crosthwaite         char *name_no_array = g_strdup(name);
127133965904SPeter Crosthwaite 
127233965904SPeter Crosthwaite         name_no_array[name_len - 3] = '\0';
12731bf8b88fSAni Sinha         for (i = 0; i < INT16_MAX; ++i) {
127433965904SPeter Crosthwaite             char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
127533965904SPeter Crosthwaite 
1276d2623129SMarkus Armbruster             ret = object_property_try_add(obj, full_name, type, get, set,
127733965904SPeter Crosthwaite                                           release, opaque, NULL);
127833965904SPeter Crosthwaite             g_free(full_name);
127933965904SPeter Crosthwaite             if (ret) {
128033965904SPeter Crosthwaite                 break;
128133965904SPeter Crosthwaite             }
128233965904SPeter Crosthwaite         }
128333965904SPeter Crosthwaite         g_free(name_no_array);
12841bf8b88fSAni Sinha         assert(ret);
128533965904SPeter Crosthwaite         return ret;
128633965904SPeter Crosthwaite     }
128754852b03SPeter Maydell 
1288efba1595SDaniel P. Berrangé     if (object_property_find(obj, name) != NULL) {
1289d55e937dSGreg Kurz         error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
1290d55e937dSGreg Kurz                    name, object_get_typename(obj));
129164607d08SPaolo Bonzini         return NULL;
129254852b03SPeter Maydell     }
129354852b03SPeter Maydell 
129454852b03SPeter Maydell     prop = g_malloc0(sizeof(*prop));
129557c9fafeSAnthony Liguori 
129657c9fafeSAnthony Liguori     prop->name = g_strdup(name);
129757c9fafeSAnthony Liguori     prop->type = g_strdup(type);
129857c9fafeSAnthony Liguori 
129957c9fafeSAnthony Liguori     prop->get = get;
130057c9fafeSAnthony Liguori     prop->set = set;
130157c9fafeSAnthony Liguori     prop->release = release;
130257c9fafeSAnthony Liguori     prop->opaque = opaque;
130357c9fafeSAnthony Liguori 
1304b604a854SPavel Fedin     g_hash_table_insert(obj->properties, prop->name, prop);
130564607d08SPaolo Bonzini     return prop;
130657c9fafeSAnthony Liguori }
130757c9fafeSAnthony Liguori 
130816bf7f52SDaniel P. Berrange ObjectProperty *
object_property_add(Object * obj,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque)1309d2623129SMarkus Armbruster object_property_add(Object *obj, const char *name, const char *type,
1310d2623129SMarkus Armbruster                     ObjectPropertyAccessor *get,
1311d2623129SMarkus Armbruster                     ObjectPropertyAccessor *set,
1312d2623129SMarkus Armbruster                     ObjectPropertyRelease *release,
1313d2623129SMarkus Armbruster                     void *opaque)
1314d2623129SMarkus Armbruster {
1315d2623129SMarkus Armbruster     return object_property_try_add(obj, name, type, get, set, release,
1316d2623129SMarkus Armbruster                                    opaque, &error_abort);
1317d2623129SMarkus Armbruster }
1318d2623129SMarkus Armbruster 
1319d2623129SMarkus Armbruster ObjectProperty *
object_class_property_add(ObjectClass * klass,const char * name,const char * type,ObjectPropertyAccessor * get,ObjectPropertyAccessor * set,ObjectPropertyRelease * release,void * opaque)132016bf7f52SDaniel P. Berrange object_class_property_add(ObjectClass *klass,
132116bf7f52SDaniel P. Berrange                           const char *name,
132216bf7f52SDaniel P. Berrange                           const char *type,
132316bf7f52SDaniel P. Berrange                           ObjectPropertyAccessor *get,
132416bf7f52SDaniel P. Berrange                           ObjectPropertyAccessor *set,
132516bf7f52SDaniel P. Berrange                           ObjectPropertyRelease *release,
1326d2623129SMarkus Armbruster                           void *opaque)
132716bf7f52SDaniel P. Berrange {
132816bf7f52SDaniel P. Berrange     ObjectProperty *prop;
132916bf7f52SDaniel P. Berrange 
1330efba1595SDaniel P. Berrangé     assert(!object_class_property_find(klass, name));
133116bf7f52SDaniel P. Berrange 
133216bf7f52SDaniel P. Berrange     prop = g_malloc0(sizeof(*prop));
133316bf7f52SDaniel P. Berrange 
133416bf7f52SDaniel P. Berrange     prop->name = g_strdup(name);
133516bf7f52SDaniel P. Berrange     prop->type = g_strdup(type);
133616bf7f52SDaniel P. Berrange 
133716bf7f52SDaniel P. Berrange     prop->get = get;
133816bf7f52SDaniel P. Berrange     prop->set = set;
133916bf7f52SDaniel P. Berrange     prop->release = release;
134016bf7f52SDaniel P. Berrange     prop->opaque = opaque;
134116bf7f52SDaniel P. Berrange 
1342ba806ffbSMarc-André Lureau     g_hash_table_insert(klass->properties, prop->name, prop);
134316bf7f52SDaniel P. Berrange 
134416bf7f52SDaniel P. Berrange     return prop;
134516bf7f52SDaniel P. Berrange }
134616bf7f52SDaniel P. Berrange 
object_property_find(Object * obj,const char * name)1347efba1595SDaniel P. Berrangé ObjectProperty *object_property_find(Object *obj, const char *name)
134857c9fafeSAnthony Liguori {
134957c9fafeSAnthony Liguori     ObjectProperty *prop;
135016bf7f52SDaniel P. Berrange     ObjectClass *klass = object_get_class(obj);
135116bf7f52SDaniel P. Berrange 
1352efba1595SDaniel P. Berrangé     prop = object_class_property_find(klass, name);
135316bf7f52SDaniel P. Berrange     if (prop) {
135416bf7f52SDaniel P. Berrange         return prop;
135516bf7f52SDaniel P. Berrange     }
135657c9fafeSAnthony Liguori 
1357efba1595SDaniel P. Berrangé     return g_hash_table_lookup(obj->properties, name);
135857c9fafeSAnthony Liguori }
135957c9fafeSAnthony Liguori 
object_property_find_err(Object * obj,const char * name,Error ** errp)1360efba1595SDaniel P. Berrangé ObjectProperty *object_property_find_err(Object *obj, const char *name,
1361efba1595SDaniel P. Berrangé                                          Error **errp)
1362efba1595SDaniel P. Berrangé {
1363efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find(obj, name);
1364efba1595SDaniel P. Berrangé     if (!prop) {
13654d9c7c84SPhilippe Mathieu-Daudé         error_setg(errp, "Property '%s.%s' not found",
13664d9c7c84SPhilippe Mathieu-Daudé                    object_get_typename(obj), name);
1367efba1595SDaniel P. Berrangé     }
1368efba1595SDaniel P. Berrangé     return prop;
136957c9fafeSAnthony Liguori }
137057c9fafeSAnthony Liguori 
object_property_iter_init(ObjectPropertyIterator * iter,Object * obj)13717746abd8SDaniel P. Berrange void object_property_iter_init(ObjectPropertyIterator *iter,
13727746abd8SDaniel P. Berrange                                Object *obj)
1373a00c9482SDaniel P. Berrange {
13747746abd8SDaniel P. Berrange     g_hash_table_iter_init(&iter->iter, obj->properties);
13757746abd8SDaniel P. Berrange     iter->nextclass = object_get_class(obj);
1376a00c9482SDaniel P. Berrange }
1377a00c9482SDaniel P. Berrange 
object_property_iter_next(ObjectPropertyIterator * iter)1378a00c9482SDaniel P. Berrange ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1379a00c9482SDaniel P. Berrange {
1380b604a854SPavel Fedin     gpointer key, val;
138116bf7f52SDaniel P. Berrange     while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
138216bf7f52SDaniel P. Berrange         if (!iter->nextclass) {
1383b604a854SPavel Fedin             return NULL;
1384a00c9482SDaniel P. Berrange         }
138516bf7f52SDaniel P. Berrange         g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
138616bf7f52SDaniel P. Berrange         iter->nextclass = object_class_get_parent(iter->nextclass);
138716bf7f52SDaniel P. Berrange     }
1388b604a854SPavel Fedin     return val;
1389a00c9482SDaniel P. Berrange }
1390a00c9482SDaniel P. Berrange 
object_class_property_iter_init(ObjectPropertyIterator * iter,ObjectClass * klass)1391961c47bbSAlexey Kardashevskiy void object_class_property_iter_init(ObjectPropertyIterator *iter,
1392961c47bbSAlexey Kardashevskiy                                      ObjectClass *klass)
1393961c47bbSAlexey Kardashevskiy {
1394961c47bbSAlexey Kardashevskiy     g_hash_table_iter_init(&iter->iter, klass->properties);
1395684546d8SMarc-André Lureau     iter->nextclass = object_class_get_parent(klass);
1396961c47bbSAlexey Kardashevskiy }
1397961c47bbSAlexey Kardashevskiy 
object_class_property_find(ObjectClass * klass,const char * name)1398efba1595SDaniel P. Berrangé ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
139916bf7f52SDaniel P. Berrange {
140016bf7f52SDaniel P. Berrange     ObjectClass *parent_klass;
140116bf7f52SDaniel P. Berrange 
140216bf7f52SDaniel P. Berrange     parent_klass = object_class_get_parent(klass);
140316bf7f52SDaniel P. Berrange     if (parent_klass) {
1404efba1595SDaniel P. Berrangé         ObjectProperty *prop =
1405efba1595SDaniel P. Berrangé             object_class_property_find(parent_klass, name);
140616bf7f52SDaniel P. Berrange         if (prop) {
140716bf7f52SDaniel P. Berrange             return prop;
140816bf7f52SDaniel P. Berrange         }
140916bf7f52SDaniel P. Berrange     }
141016bf7f52SDaniel P. Berrange 
1411efba1595SDaniel P. Berrangé     return g_hash_table_lookup(klass->properties, name);
1412efba1595SDaniel P. Berrangé }
1413efba1595SDaniel P. Berrangé 
object_class_property_find_err(ObjectClass * klass,const char * name,Error ** errp)1414efba1595SDaniel P. Berrangé ObjectProperty *object_class_property_find_err(ObjectClass *klass,
1415efba1595SDaniel P. Berrangé                                                const char *name,
1416efba1595SDaniel P. Berrangé                                                Error **errp)
1417efba1595SDaniel P. Berrangé {
1418efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_class_property_find(klass, name);
141916bf7f52SDaniel P. Berrange     if (!prop) {
142016bf7f52SDaniel P. Berrange         error_setg(errp, "Property '.%s' not found", name);
142116bf7f52SDaniel P. Berrange     }
142216bf7f52SDaniel P. Berrange     return prop;
142316bf7f52SDaniel P. Berrange }
142416bf7f52SDaniel P. Berrange 
1425efba1595SDaniel P. Berrangé 
object_property_del(Object * obj,const char * name)1426df4fe0b2SMarkus Armbruster void object_property_del(Object *obj, const char *name)
142757c9fafeSAnthony Liguori {
1428b604a854SPavel Fedin     ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1429b604a854SPavel Fedin 
14300866aca1SAnthony Liguori     if (prop->release) {
14310866aca1SAnthony Liguori         prop->release(obj, name, prop->opaque);
14320866aca1SAnthony Liguori     }
1433b604a854SPavel Fedin     g_hash_table_remove(obj->properties, name);
143457c9fafeSAnthony Liguori }
143557c9fafeSAnthony Liguori 
object_property_get(Object * obj,const char * name,Visitor * v,Error ** errp)14366fd5bef1SMarkus Armbruster bool object_property_get(Object *obj, const char *name, Visitor *v,
143757c9fafeSAnthony Liguori                          Error **errp)
143857c9fafeSAnthony Liguori {
14396fd5bef1SMarkus Armbruster     Error *err = NULL;
1440efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find_err(obj, name, errp);
14416fd5bef1SMarkus Armbruster 
144257c9fafeSAnthony Liguori     if (prop == NULL) {
14436fd5bef1SMarkus Armbruster         return false;
144457c9fafeSAnthony Liguori     }
144557c9fafeSAnthony Liguori 
144657c9fafeSAnthony Liguori     if (!prop->get) {
14473f7febc9SMarkus Armbruster         error_setg(errp, "Property '%s.%s' is not readable",
14483f7febc9SMarkus Armbruster                    object_get_typename(obj), name);
14496fd5bef1SMarkus Armbruster         return false;
145057c9fafeSAnthony Liguori     }
14516fd5bef1SMarkus Armbruster     prop->get(obj, v, name, prop->opaque, &err);
14526fd5bef1SMarkus Armbruster     error_propagate(errp, err);
14536fd5bef1SMarkus Armbruster     return !err;
145457c9fafeSAnthony Liguori }
145557c9fafeSAnthony Liguori 
object_property_set(Object * obj,const char * name,Visitor * v,Error ** errp)14566fd5bef1SMarkus Armbruster bool object_property_set(Object *obj, const char *name, Visitor *v,
145757c9fafeSAnthony Liguori                          Error **errp)
145857c9fafeSAnthony Liguori {
1459dbc8221fSKevin Wolf     ERRP_GUARD();
1460efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find_err(obj, name, errp);
14616fd5bef1SMarkus Armbruster 
146257c9fafeSAnthony Liguori     if (prop == NULL) {
14636fd5bef1SMarkus Armbruster         return false;
146457c9fafeSAnthony Liguori     }
146557c9fafeSAnthony Liguori 
146657c9fafeSAnthony Liguori     if (!prop->set) {
14673f7febc9SMarkus Armbruster         error_setg(errp, "Property '%s.%s' is not writable",
14683f7febc9SMarkus Armbruster                    object_get_typename(obj), name);
14696fd5bef1SMarkus Armbruster         return false;
147057c9fafeSAnthony Liguori     }
1471dbc8221fSKevin Wolf     prop->set(obj, v, name, prop->opaque, errp);
1472dbc8221fSKevin Wolf     return !*errp;
147357c9fafeSAnthony Liguori }
147457c9fafeSAnthony Liguori 
object_property_set_str(Object * obj,const char * name,const char * value,Error ** errp)14756fd5bef1SMarkus Armbruster bool object_property_set_str(Object *obj, const char *name,
14765325cc34SMarkus Armbruster                              const char *value, Error **errp)
14777b7b7d18SPaolo Bonzini {
14787b7b7d18SPaolo Bonzini     QString *qstr = qstring_from_str(value);
14796fd5bef1SMarkus Armbruster     bool ok = object_property_set_qobject(obj, name, QOBJECT(qstr), errp);
14807b7b7d18SPaolo Bonzini 
1481cb3e7f08SMarc-André Lureau     qobject_unref(qstr);
14826fd5bef1SMarkus Armbruster     return ok;
14837b7b7d18SPaolo Bonzini }
14847b7b7d18SPaolo Bonzini 
object_property_get_str(Object * obj,const char * name,Error ** errp)14857b7b7d18SPaolo Bonzini char *object_property_get_str(Object *obj, const char *name,
14867b7b7d18SPaolo Bonzini                               Error **errp)
14877b7b7d18SPaolo Bonzini {
14887b7b7d18SPaolo Bonzini     QObject *ret = object_property_get_qobject(obj, name, errp);
148926c52828SMarkus Armbruster     QString *qstring;
14907b7b7d18SPaolo Bonzini     char *retval;
14917b7b7d18SPaolo Bonzini 
14927b7b7d18SPaolo Bonzini     if (!ret) {
14937b7b7d18SPaolo Bonzini         return NULL;
14947b7b7d18SPaolo Bonzini     }
149526c52828SMarkus Armbruster     qstring = qobject_to(QString, ret);
149626c52828SMarkus Armbruster     if (!qstring) {
1497aaeafa50SPhilippe Mathieu-Daudé         error_setg(errp, "Invalid parameter type for '%s', expected: string",
1498aaeafa50SPhilippe Mathieu-Daudé                    name);
149926c52828SMarkus Armbruster         retval = NULL;
150026c52828SMarkus Armbruster     } else {
150126c52828SMarkus Armbruster         retval = g_strdup(qstring_get_str(qstring));
15027b7b7d18SPaolo Bonzini     }
15037b7b7d18SPaolo Bonzini 
1504cb3e7f08SMarc-André Lureau     qobject_unref(ret);
15057b7b7d18SPaolo Bonzini     return retval;
15067b7b7d18SPaolo Bonzini }
15077b7b7d18SPaolo Bonzini 
object_property_set_link(Object * obj,const char * name,Object * value,Error ** errp)15086fd5bef1SMarkus Armbruster bool object_property_set_link(Object *obj, const char *name,
15095325cc34SMarkus Armbruster                               Object *value, Error **errp)
15101d9c5a12SPaolo Bonzini {
15116fd5bef1SMarkus Armbruster     g_autofree char *path = NULL;
15126fd5bef1SMarkus Armbruster 
1513d3c49316SPeter Crosthwaite     if (value) {
15146fd5bef1SMarkus Armbruster         path = object_get_canonical_path(value);
1515d3c49316SPeter Crosthwaite     }
15166fd5bef1SMarkus Armbruster     return object_property_set_str(obj, name, path ?: "", errp);
15171d9c5a12SPaolo Bonzini }
15181d9c5a12SPaolo Bonzini 
object_property_get_link(Object * obj,const char * name,Error ** errp)15191d9c5a12SPaolo Bonzini Object *object_property_get_link(Object *obj, const char *name,
15201d9c5a12SPaolo Bonzini                                  Error **errp)
15211d9c5a12SPaolo Bonzini {
15221d9c5a12SPaolo Bonzini     char *str = object_property_get_str(obj, name, errp);
15231d9c5a12SPaolo Bonzini     Object *target = NULL;
15241d9c5a12SPaolo Bonzini 
15251d9c5a12SPaolo Bonzini     if (str && *str) {
15261d9c5a12SPaolo Bonzini         target = object_resolve_path(str, NULL);
15271d9c5a12SPaolo Bonzini         if (!target) {
152875158ebbSMarkus Armbruster             error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
152975158ebbSMarkus Armbruster                       "Device '%s' not found", str);
15301d9c5a12SPaolo Bonzini         }
15311d9c5a12SPaolo Bonzini     }
15321d9c5a12SPaolo Bonzini 
15331d9c5a12SPaolo Bonzini     g_free(str);
15341d9c5a12SPaolo Bonzini     return target;
15351d9c5a12SPaolo Bonzini }
15361d9c5a12SPaolo Bonzini 
object_property_set_bool(Object * obj,const char * name,bool value,Error ** errp)15376fd5bef1SMarkus Armbruster bool object_property_set_bool(Object *obj, const char *name,
15385325cc34SMarkus Armbruster                               bool value, Error **errp)
15397b7b7d18SPaolo Bonzini {
1540fc48ffc3SEric Blake     QBool *qbool = qbool_from_bool(value);
15416fd5bef1SMarkus Armbruster     bool ok = object_property_set_qobject(obj, name, QOBJECT(qbool), errp);
15427b7b7d18SPaolo Bonzini 
1543cb3e7f08SMarc-André Lureau     qobject_unref(qbool);
15446fd5bef1SMarkus Armbruster     return ok;
15457b7b7d18SPaolo Bonzini }
15467b7b7d18SPaolo Bonzini 
object_property_get_bool(Object * obj,const char * name,Error ** errp)15477b7b7d18SPaolo Bonzini bool object_property_get_bool(Object *obj, const char *name,
15487b7b7d18SPaolo Bonzini                               Error **errp)
15497b7b7d18SPaolo Bonzini {
15507b7b7d18SPaolo Bonzini     QObject *ret = object_property_get_qobject(obj, name, errp);
15517b7b7d18SPaolo Bonzini     QBool *qbool;
15527b7b7d18SPaolo Bonzini     bool retval;
15537b7b7d18SPaolo Bonzini 
15547b7b7d18SPaolo Bonzini     if (!ret) {
15557b7b7d18SPaolo Bonzini         return false;
15567b7b7d18SPaolo Bonzini     }
15577dc847ebSMax Reitz     qbool = qobject_to(QBool, ret);
15587b7b7d18SPaolo Bonzini     if (!qbool) {
1559aaeafa50SPhilippe Mathieu-Daudé         error_setg(errp, "Invalid parameter type for '%s', expected: boolean",
1560aaeafa50SPhilippe Mathieu-Daudé                    name);
15617b7b7d18SPaolo Bonzini         retval = false;
15627b7b7d18SPaolo Bonzini     } else {
1563fc48ffc3SEric Blake         retval = qbool_get_bool(qbool);
15647b7b7d18SPaolo Bonzini     }
15657b7b7d18SPaolo Bonzini 
1566cb3e7f08SMarc-André Lureau     qobject_unref(ret);
15677b7b7d18SPaolo Bonzini     return retval;
15687b7b7d18SPaolo Bonzini }
15697b7b7d18SPaolo Bonzini 
object_property_set_int(Object * obj,const char * name,int64_t value,Error ** errp)15706fd5bef1SMarkus Armbruster bool object_property_set_int(Object *obj, const char *name,
15715325cc34SMarkus Armbruster                              int64_t value, Error **errp)
15727b7b7d18SPaolo Bonzini {
157301b2ffceSMarc-André Lureau     QNum *qnum = qnum_from_int(value);
15746fd5bef1SMarkus Armbruster     bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
15757b7b7d18SPaolo Bonzini 
1576cb3e7f08SMarc-André Lureau     qobject_unref(qnum);
15776fd5bef1SMarkus Armbruster     return ok;
15787b7b7d18SPaolo Bonzini }
15797b7b7d18SPaolo Bonzini 
object_property_get_int(Object * obj,const char * name,Error ** errp)15807b7b7d18SPaolo Bonzini int64_t object_property_get_int(Object *obj, const char *name,
15817b7b7d18SPaolo Bonzini                                 Error **errp)
15827b7b7d18SPaolo Bonzini {
15837b7b7d18SPaolo Bonzini     QObject *ret = object_property_get_qobject(obj, name, errp);
158401b2ffceSMarc-André Lureau     QNum *qnum;
15857b7b7d18SPaolo Bonzini     int64_t retval;
15867b7b7d18SPaolo Bonzini 
15877b7b7d18SPaolo Bonzini     if (!ret) {
15887b7b7d18SPaolo Bonzini         return -1;
15897b7b7d18SPaolo Bonzini     }
159001b2ffceSMarc-André Lureau 
15917dc847ebSMax Reitz     qnum = qobject_to(QNum, ret);
159201b2ffceSMarc-André Lureau     if (!qnum || !qnum_get_try_int(qnum, &retval)) {
1593aaeafa50SPhilippe Mathieu-Daudé         error_setg(errp, "Invalid parameter type for '%s', expected: int",
1594aaeafa50SPhilippe Mathieu-Daudé                    name);
15957b7b7d18SPaolo Bonzini         retval = -1;
15967b7b7d18SPaolo Bonzini     }
15977b7b7d18SPaolo Bonzini 
1598cb3e7f08SMarc-André Lureau     qobject_unref(ret);
15997b7b7d18SPaolo Bonzini     return retval;
16007b7b7d18SPaolo Bonzini }
16017b7b7d18SPaolo Bonzini 
object_property_init_defval(Object * obj,ObjectProperty * prop)16020e76ed0aSMarc-André Lureau static void object_property_init_defval(Object *obj, ObjectProperty *prop)
16030e76ed0aSMarc-André Lureau {
16040e76ed0aSMarc-André Lureau     Visitor *v = qobject_input_visitor_new(prop->defval);
16050e76ed0aSMarc-André Lureau 
16060e76ed0aSMarc-André Lureau     assert(prop->set != NULL);
16070e76ed0aSMarc-André Lureau     prop->set(obj, v, prop->name, prop->opaque, &error_abort);
16080e76ed0aSMarc-André Lureau 
16090e76ed0aSMarc-André Lureau     visit_free(v);
16100e76ed0aSMarc-André Lureau }
16110e76ed0aSMarc-André Lureau 
object_property_set_default(ObjectProperty * prop,QObject * defval)16120e76ed0aSMarc-André Lureau static void object_property_set_default(ObjectProperty *prop, QObject *defval)
16130e76ed0aSMarc-André Lureau {
16140e76ed0aSMarc-André Lureau     assert(!prop->defval);
16150e76ed0aSMarc-André Lureau     assert(!prop->init);
16160e76ed0aSMarc-André Lureau 
16170e76ed0aSMarc-André Lureau     prop->defval = defval;
16180e76ed0aSMarc-André Lureau     prop->init = object_property_init_defval;
16190e76ed0aSMarc-André Lureau }
16200e76ed0aSMarc-André Lureau 
object_property_set_default_bool(ObjectProperty * prop,bool value)16210e76ed0aSMarc-André Lureau void object_property_set_default_bool(ObjectProperty *prop, bool value)
16220e76ed0aSMarc-André Lureau {
16230e76ed0aSMarc-André Lureau     object_property_set_default(prop, QOBJECT(qbool_from_bool(value)));
16240e76ed0aSMarc-André Lureau }
16250e76ed0aSMarc-André Lureau 
object_property_set_default_str(ObjectProperty * prop,const char * value)16260e76ed0aSMarc-André Lureau void object_property_set_default_str(ObjectProperty *prop, const char *value)
16270e76ed0aSMarc-André Lureau {
16280e76ed0aSMarc-André Lureau     object_property_set_default(prop, QOBJECT(qstring_from_str(value)));
16290e76ed0aSMarc-André Lureau }
16300e76ed0aSMarc-André Lureau 
object_property_set_default_list(ObjectProperty * prop)1631125062e7SKevin Wolf void object_property_set_default_list(ObjectProperty *prop)
1632125062e7SKevin Wolf {
1633125062e7SKevin Wolf     object_property_set_default(prop, QOBJECT(qlist_new()));
1634125062e7SKevin Wolf }
1635125062e7SKevin Wolf 
object_property_set_default_int(ObjectProperty * prop,int64_t value)16360e76ed0aSMarc-André Lureau void object_property_set_default_int(ObjectProperty *prop, int64_t value)
16370e76ed0aSMarc-André Lureau {
16380e76ed0aSMarc-André Lureau     object_property_set_default(prop, QOBJECT(qnum_from_int(value)));
16390e76ed0aSMarc-André Lureau }
16400e76ed0aSMarc-André Lureau 
object_property_set_default_uint(ObjectProperty * prop,uint64_t value)16410e76ed0aSMarc-André Lureau void object_property_set_default_uint(ObjectProperty *prop, uint64_t value)
16420e76ed0aSMarc-André Lureau {
16430e76ed0aSMarc-André Lureau     object_property_set_default(prop, QOBJECT(qnum_from_uint(value)));
16440e76ed0aSMarc-André Lureau }
16450e76ed0aSMarc-André Lureau 
object_property_set_uint(Object * obj,const char * name,uint64_t value,Error ** errp)16466fd5bef1SMarkus Armbruster bool object_property_set_uint(Object *obj, const char *name,
16475325cc34SMarkus Armbruster                               uint64_t value, Error **errp)
16483152779cSMarc-André Lureau {
16493152779cSMarc-André Lureau     QNum *qnum = qnum_from_uint(value);
16506fd5bef1SMarkus Armbruster     bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
16513152779cSMarc-André Lureau 
1652cb3e7f08SMarc-André Lureau     qobject_unref(qnum);
16536fd5bef1SMarkus Armbruster     return ok;
16543152779cSMarc-André Lureau }
16553152779cSMarc-André Lureau 
object_property_get_uint(Object * obj,const char * name,Error ** errp)16563152779cSMarc-André Lureau uint64_t object_property_get_uint(Object *obj, const char *name,
16573152779cSMarc-André Lureau                                   Error **errp)
16583152779cSMarc-André Lureau {
16593152779cSMarc-André Lureau     QObject *ret = object_property_get_qobject(obj, name, errp);
16603152779cSMarc-André Lureau     QNum *qnum;
16613152779cSMarc-André Lureau     uint64_t retval;
16623152779cSMarc-André Lureau 
16633152779cSMarc-André Lureau     if (!ret) {
16643152779cSMarc-André Lureau         return 0;
16653152779cSMarc-André Lureau     }
16667dc847ebSMax Reitz     qnum = qobject_to(QNum, ret);
16673152779cSMarc-André Lureau     if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
1668aaeafa50SPhilippe Mathieu-Daudé         error_setg(errp, "Invalid parameter type for '%s', expected: uint",
1669aaeafa50SPhilippe Mathieu-Daudé                    name);
16703152779cSMarc-André Lureau         retval = 0;
16713152779cSMarc-André Lureau     }
16723152779cSMarc-André Lureau 
1673cb3e7f08SMarc-André Lureau     qobject_unref(ret);
16743152779cSMarc-André Lureau     return retval;
16753152779cSMarc-André Lureau }
16763152779cSMarc-André Lureau 
1677a8e3fbedSDaniel P. Berrange typedef struct EnumProperty {
1678f7abe0ecSMarc-André Lureau     const QEnumLookup *lookup;
1679a8e3fbedSDaniel P. Berrange     int (*get)(Object *, Error **);
1680a8e3fbedSDaniel P. Berrange     void (*set)(Object *, int, Error **);
1681a8e3fbedSDaniel P. Berrange } EnumProperty;
1682a8e3fbedSDaniel P. Berrange 
object_property_get_enum(Object * obj,const char * name,const char * typename,Error ** errp)16831f21772dSHu Tao int object_property_get_enum(Object *obj, const char *name,
1684a3590dacSDaniel P. Berrange                              const char *typename, Error **errp)
16851f21772dSHu Tao {
1686976620acSChen Fan     char *str;
16871f21772dSHu Tao     int ret;
1688efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find_err(obj, name, errp);
1689a3590dacSDaniel P. Berrange     EnumProperty *enumprop;
1690a3590dacSDaniel P. Berrange 
1691a3590dacSDaniel P. Berrange     if (prop == NULL) {
1692d20f616eSMarkus Armbruster         return -1;
1693a3590dacSDaniel P. Berrange     }
1694a3590dacSDaniel P. Berrange 
1695a3590dacSDaniel P. Berrange     if (!g_str_equal(prop->type, typename)) {
1696a3590dacSDaniel P. Berrange         error_setg(errp, "Property %s on %s is not '%s' enum type",
1697a3590dacSDaniel P. Berrange                    name, object_class_get_name(
1698a3590dacSDaniel P. Berrange                        object_get_class(obj)), typename);
1699d20f616eSMarkus Armbruster         return -1;
1700a3590dacSDaniel P. Berrange     }
1701a3590dacSDaniel P. Berrange 
1702a3590dacSDaniel P. Berrange     enumprop = prop->opaque;
17031f21772dSHu Tao 
1704b555f89fSMarkus Armbruster     str = object_property_get_str(obj, name, errp);
1705b555f89fSMarkus Armbruster     if (!str) {
1706d20f616eSMarkus Armbruster         return -1;
17074715d42eSMarkus Armbruster     }
1708976620acSChen Fan 
1709ea097dffSMarkus Armbruster     ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
1710976620acSChen Fan     g_free(str);
17111f21772dSHu Tao 
17121f21772dSHu Tao     return ret;
17131f21772dSHu Tao }
17141f21772dSHu Tao 
object_property_parse(Object * obj,const char * name,const char * string,Error ** errp)17156fd5bef1SMarkus Armbruster bool object_property_parse(Object *obj, const char *name,
17165325cc34SMarkus Armbruster                            const char *string, Error **errp)
1717b2cd7deeSPaolo Bonzini {
17187a0525c7SEric Blake     Visitor *v = string_input_visitor_new(string);
17196fd5bef1SMarkus Armbruster     bool ok = object_property_set(obj, name, v, errp);
17206fd5bef1SMarkus Armbruster 
17217a0525c7SEric Blake     visit_free(v);
17226fd5bef1SMarkus Armbruster     return ok;
1723b2cd7deeSPaolo Bonzini }
1724b2cd7deeSPaolo Bonzini 
object_property_print(Object * obj,const char * name,bool human,Error ** errp)17250b7593e0SPaolo Bonzini char *object_property_print(Object *obj, const char *name, bool human,
1726b2cd7deeSPaolo Bonzini                             Error **errp)
1727b2cd7deeSPaolo Bonzini {
17283b098d56SEric Blake     Visitor *v;
17293a53009fSGonglei     char *string = NULL;
1730b2cd7deeSPaolo Bonzini 
17313b098d56SEric Blake     v = string_output_visitor_new(human, &string);
1732af175e85SMarkus Armbruster     if (!object_property_get(obj, name, v, errp)) {
17333a53009fSGonglei         goto out;
17343a53009fSGonglei     }
17353a53009fSGonglei 
17363b098d56SEric Blake     visit_complete(v, &string);
17373a53009fSGonglei 
17383a53009fSGonglei out:
17393b098d56SEric Blake     visit_free(v);
1740b2cd7deeSPaolo Bonzini     return string;
1741b2cd7deeSPaolo Bonzini }
1742b2cd7deeSPaolo Bonzini 
object_property_get_type(Object * obj,const char * name,Error ** errp)174357c9fafeSAnthony Liguori const char *object_property_get_type(Object *obj, const char *name, Error **errp)
174457c9fafeSAnthony Liguori {
1745efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find_err(obj, name, errp);
174657c9fafeSAnthony Liguori     if (prop == NULL) {
174757c9fafeSAnthony Liguori         return NULL;
174857c9fafeSAnthony Liguori     }
174957c9fafeSAnthony Liguori 
175057c9fafeSAnthony Liguori     return prop->type;
175157c9fafeSAnthony Liguori }
175257c9fafeSAnthony Liguori 
object_get_root(void)175357c9fafeSAnthony Liguori Object *object_get_root(void)
175457c9fafeSAnthony Liguori {
17558b45d447SAnthony Liguori     static Object *root;
175657c9fafeSAnthony Liguori 
17578b45d447SAnthony Liguori     if (!root) {
17588b45d447SAnthony Liguori         root = object_new("container");
175957c9fafeSAnthony Liguori     }
176057c9fafeSAnthony Liguori 
17618b45d447SAnthony Liguori     return root;
176257c9fafeSAnthony Liguori }
176357c9fafeSAnthony Liguori 
object_get_objects_root(void)1764bc2256c4SDaniel P. Berrange Object *object_get_objects_root(void)
1765bc2256c4SDaniel P. Berrange {
1766bc2256c4SDaniel P. Berrange     return container_get(object_get_root(), "/objects");
1767bc2256c4SDaniel P. Berrange }
1768bc2256c4SDaniel P. Berrange 
object_get_internal_root(void)17697c47c4eaSPeter Xu Object *object_get_internal_root(void)
17707c47c4eaSPeter Xu {
17717c47c4eaSPeter Xu     static Object *internal_root;
17727c47c4eaSPeter Xu 
17737c47c4eaSPeter Xu     if (!internal_root) {
17747c47c4eaSPeter Xu         internal_root = object_new("container");
17757c47c4eaSPeter Xu     }
17767c47c4eaSPeter Xu 
17777c47c4eaSPeter Xu     return internal_root;
17787c47c4eaSPeter Xu }
17797c47c4eaSPeter Xu 
object_get_child_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1780d7bce999SEric Blake static void object_get_child_property(Object *obj, Visitor *v,
1781d7bce999SEric Blake                                       const char *name, void *opaque,
1782d7bce999SEric Blake                                       Error **errp)
178357c9fafeSAnthony Liguori {
178457c9fafeSAnthony Liguori     Object *child = opaque;
1785ddfb0baaSMarkus Armbruster     char *path;
178657c9fafeSAnthony Liguori 
178757c9fafeSAnthony Liguori     path = object_get_canonical_path(child);
178851e72bc1SEric Blake     visit_type_str(v, name, &path, errp);
178957c9fafeSAnthony Liguori     g_free(path);
179057c9fafeSAnthony Liguori }
179157c9fafeSAnthony Liguori 
object_resolve_child_property(Object * parent,void * opaque,const char * part)1792ddfb0baaSMarkus Armbruster static Object *object_resolve_child_property(Object *parent, void *opaque,
1793ddfb0baaSMarkus Armbruster                                              const char *part)
179464607d08SPaolo Bonzini {
179564607d08SPaolo Bonzini     return opaque;
179664607d08SPaolo Bonzini }
179764607d08SPaolo Bonzini 
object_finalize_child_property(Object * obj,const char * name,void * opaque)1798db85b575SAnthony Liguori static void object_finalize_child_property(Object *obj, const char *name,
1799db85b575SAnthony Liguori                                            void *opaque)
1800db85b575SAnthony Liguori {
1801db85b575SAnthony Liguori     Object *child = opaque;
1802db85b575SAnthony Liguori 
1803bffc687dSPaolo Bonzini     if (child->class->unparent) {
1804bffc687dSPaolo Bonzini         (child->class->unparent)(child);
1805bffc687dSPaolo Bonzini     }
1806bffc687dSPaolo Bonzini     child->parent = NULL;
1807db85b575SAnthony Liguori     object_unref(child);
1808db85b575SAnthony Liguori }
1809db85b575SAnthony Liguori 
181070251887SMarkus Armbruster ObjectProperty *
object_property_try_add_child(Object * obj,const char * name,Object * child,Error ** errp)1811db57fef1SEric Auger object_property_try_add_child(Object *obj, const char *name,
1812db57fef1SEric Auger                               Object *child, Error **errp)
181357c9fafeSAnthony Liguori {
181470251887SMarkus Armbruster     g_autofree char *type = NULL;
181564607d08SPaolo Bonzini     ObjectProperty *op;
181657c9fafeSAnthony Liguori 
1817d2623129SMarkus Armbruster     assert(!child->parent);
18188faa2f85SPeter Crosthwaite 
1819688ffbb4SPhilippe Mathieu-Daudé     type = g_strdup_printf("child<%s>", object_get_typename(child));
182057c9fafeSAnthony Liguori 
1821db57fef1SEric Auger     op = object_property_try_add(obj, name, type, object_get_child_property,
1822db57fef1SEric Auger                                  NULL, object_finalize_child_property,
1823db57fef1SEric Auger                                  child, errp);
1824db57fef1SEric Auger     if (!op) {
1825db57fef1SEric Auger         return NULL;
1826db57fef1SEric Auger     }
182764607d08SPaolo Bonzini     op->resolve = object_resolve_child_property;
182857c9fafeSAnthony Liguori     object_ref(child);
182957c9fafeSAnthony Liguori     child->parent = obj;
183070251887SMarkus Armbruster     return op;
183157c9fafeSAnthony Liguori }
183257c9fafeSAnthony Liguori 
1833db57fef1SEric Auger ObjectProperty *
object_property_add_child(Object * obj,const char * name,Object * child)1834db57fef1SEric Auger object_property_add_child(Object *obj, const char *name,
1835db57fef1SEric Auger                           Object *child)
1836db57fef1SEric Auger {
1837db57fef1SEric Auger     return object_property_try_add_child(obj, name, child, &error_abort);
1838db57fef1SEric Auger }
1839db57fef1SEric Auger 
object_property_allow_set_link(const Object * obj,const char * name,Object * val,Error ** errp)18408f5d58efSIgor Mammedov void object_property_allow_set_link(const Object *obj, const char *name,
184139f72ef9SStefan Hajnoczi                                     Object *val, Error **errp)
184239f72ef9SStefan Hajnoczi {
184339f72ef9SStefan Hajnoczi     /* Allow the link to be set, always */
184439f72ef9SStefan Hajnoczi }
184539f72ef9SStefan Hajnoczi 
18469561fda8SStefan Hajnoczi typedef struct {
18479941d37bSMarc-André Lureau     union {
184836854207SMarc-André Lureau         Object **targetp;
18499941d37bSMarc-André Lureau         Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer  */
1850840ecdfbSMarc-André Lureau         ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */
18519941d37bSMarc-André Lureau     };
18528f5d58efSIgor Mammedov     void (*check)(const Object *, const char *, Object *, Error **);
18539561fda8SStefan Hajnoczi     ObjectPropertyLinkFlags flags;
18549561fda8SStefan Hajnoczi } LinkProperty;
18559561fda8SStefan Hajnoczi 
18569941d37bSMarc-André Lureau static Object **
object_link_get_targetp(Object * obj,LinkProperty * lprop)18579941d37bSMarc-André Lureau object_link_get_targetp(Object *obj, LinkProperty *lprop)
18589941d37bSMarc-André Lureau {
18599941d37bSMarc-André Lureau     if (lprop->flags & OBJ_PROP_LINK_DIRECT) {
18609941d37bSMarc-André Lureau         return &lprop->target;
1861840ecdfbSMarc-André Lureau     } else if (lprop->flags & OBJ_PROP_LINK_CLASS) {
1862840ecdfbSMarc-André Lureau         return (void *)obj + lprop->offset;
18639941d37bSMarc-André Lureau     } else {
18649941d37bSMarc-André Lureau         return lprop->targetp;
18659941d37bSMarc-André Lureau     }
18669941d37bSMarc-André Lureau }
18679941d37bSMarc-André Lureau 
object_get_link_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1868d7bce999SEric Blake static void object_get_link_property(Object *obj, Visitor *v,
1869d7bce999SEric Blake                                      const char *name, void *opaque,
1870d7bce999SEric Blake                                      Error **errp)
187157c9fafeSAnthony Liguori {
18729561fda8SStefan Hajnoczi     LinkProperty *lprop = opaque;
18739941d37bSMarc-André Lureau     Object **targetp = object_link_get_targetp(obj, lprop);
1874ddfb0baaSMarkus Armbruster     char *path;
187557c9fafeSAnthony Liguori 
187636854207SMarc-André Lureau     if (*targetp) {
187736854207SMarc-André Lureau         path = object_get_canonical_path(*targetp);
187851e72bc1SEric Blake         visit_type_str(v, name, &path, errp);
187957c9fafeSAnthony Liguori         g_free(path);
188057c9fafeSAnthony Liguori     } else {
1881ddfb0baaSMarkus Armbruster         path = (char *)"";
188251e72bc1SEric Blake         visit_type_str(v, name, &path, errp);
188357c9fafeSAnthony Liguori     }
188457c9fafeSAnthony Liguori }
188557c9fafeSAnthony Liguori 
1886f5ec6704SStefan Hajnoczi /*
1887f5ec6704SStefan Hajnoczi  * object_resolve_link:
1888f5ec6704SStefan Hajnoczi  *
1889f5ec6704SStefan Hajnoczi  * Lookup an object and ensure its type matches the link property type.  This
1890f5ec6704SStefan Hajnoczi  * is similar to object_resolve_path() except type verification against the
1891f5ec6704SStefan Hajnoczi  * link property is performed.
1892f5ec6704SStefan Hajnoczi  *
1893f5ec6704SStefan Hajnoczi  * Returns: The matched object or NULL on path lookup failures.
1894f5ec6704SStefan Hajnoczi  */
object_resolve_link(Object * obj,const char * name,const char * path,Error ** errp)1895f5ec6704SStefan Hajnoczi static Object *object_resolve_link(Object *obj, const char *name,
1896f5ec6704SStefan Hajnoczi                                    const char *path, Error **errp)
1897f5ec6704SStefan Hajnoczi {
1898f5ec6704SStefan Hajnoczi     const char *type;
1899ddfb0baaSMarkus Armbruster     char *target_type;
1900f5ec6704SStefan Hajnoczi     bool ambiguous = false;
1901f5ec6704SStefan Hajnoczi     Object *target;
1902f5ec6704SStefan Hajnoczi 
1903f5ec6704SStefan Hajnoczi     /* Go from link<FOO> to FOO.  */
1904f5ec6704SStefan Hajnoczi     type = object_property_get_type(obj, name, NULL);
1905f5ec6704SStefan Hajnoczi     target_type = g_strndup(&type[5], strlen(type) - 6);
1906f5ec6704SStefan Hajnoczi     target = object_resolve_path_type(path, target_type, &ambiguous);
1907f5ec6704SStefan Hajnoczi 
1908f5ec6704SStefan Hajnoczi     if (ambiguous) {
1909455b0fdeSEric Blake         error_setg(errp, "Path '%s' does not uniquely identify an object",
1910455b0fdeSEric Blake                    path);
1911f5ec6704SStefan Hajnoczi     } else if (!target) {
1912f5ec6704SStefan Hajnoczi         target = object_resolve_path(path, &ambiguous);
1913f5ec6704SStefan Hajnoczi         if (target || ambiguous) {
1914*ef929281SPhilippe Mathieu-Daudé             error_setg(errp, "Invalid parameter type for '%s', expected: %s",
1915*ef929281SPhilippe Mathieu-Daudé                              name, target_type);
1916f5ec6704SStefan Hajnoczi         } else {
191775158ebbSMarkus Armbruster             error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
191875158ebbSMarkus Armbruster                       "Device '%s' not found", path);
1919f5ec6704SStefan Hajnoczi         }
1920f5ec6704SStefan Hajnoczi         target = NULL;
1921f5ec6704SStefan Hajnoczi     }
1922f5ec6704SStefan Hajnoczi     g_free(target_type);
1923f5ec6704SStefan Hajnoczi 
1924f5ec6704SStefan Hajnoczi     return target;
1925f5ec6704SStefan Hajnoczi }
1926f5ec6704SStefan Hajnoczi 
object_set_link_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1927d7bce999SEric Blake static void object_set_link_property(Object *obj, Visitor *v,
1928d7bce999SEric Blake                                      const char *name, void *opaque,
1929d7bce999SEric Blake                                      Error **errp)
193057c9fafeSAnthony Liguori {
1931c6aed983SStefan Hajnoczi     Error *local_err = NULL;
19329561fda8SStefan Hajnoczi     LinkProperty *prop = opaque;
19339941d37bSMarc-André Lureau     Object **targetp = object_link_get_targetp(obj, prop);
193436854207SMarc-André Lureau     Object *old_target = *targetp;
19351c94a351SMarkus Armbruster     Object *new_target;
1936c6aed983SStefan Hajnoczi     char *path = NULL;
193757c9fafeSAnthony Liguori 
19381c94a351SMarkus Armbruster     if (!visit_type_str(v, name, &path, errp)) {
19391c94a351SMarkus Armbruster         return;
19401c94a351SMarkus Armbruster     }
194157c9fafeSAnthony Liguori 
19421c94a351SMarkus Armbruster     if (*path) {
19431c94a351SMarkus Armbruster         new_target = object_resolve_link(obj, name, path, errp);
19441c94a351SMarkus Armbruster         if (!new_target) {
19451c94a351SMarkus Armbruster             g_free(path);
19461c94a351SMarkus Armbruster             return;
19471c94a351SMarkus Armbruster         }
19481c94a351SMarkus Armbruster     } else {
19491c94a351SMarkus Armbruster         new_target = NULL;
195011e35bfdSPaolo Bonzini     }
195157c9fafeSAnthony Liguori 
195257c9fafeSAnthony Liguori     g_free(path);
1953f0cdc966SAlexander Barabash 
195439f72ef9SStefan Hajnoczi     prop->check(obj, name, new_target, &local_err);
195539f72ef9SStefan Hajnoczi     if (local_err) {
195639f72ef9SStefan Hajnoczi         error_propagate(errp, local_err);
195739f72ef9SStefan Hajnoczi         return;
195839f72ef9SStefan Hajnoczi     }
195939f72ef9SStefan Hajnoczi 
196036854207SMarc-André Lureau     *targetp = new_target;
19618770bafdSMarc-André Lureau     if (prop->flags & OBJ_PROP_LINK_STRONG) {
1962265b578cSMarc-André Lureau         object_ref(new_target);
1963f0cdc966SAlexander Barabash         object_unref(old_target);
1964f0cdc966SAlexander Barabash     }
1965265b578cSMarc-André Lureau }
196657c9fafeSAnthony Liguori 
object_resolve_link_property(Object * parent,void * opaque,const char * part)1967ddfb0baaSMarkus Armbruster static Object *object_resolve_link_property(Object *parent, void *opaque,
1968ddfb0baaSMarkus Armbruster                                             const char *part)
196964607d08SPaolo Bonzini {
197064607d08SPaolo Bonzini     LinkProperty *lprop = opaque;
197164607d08SPaolo Bonzini 
19729941d37bSMarc-André Lureau     return *object_link_get_targetp(parent, lprop);
197364607d08SPaolo Bonzini }
197464607d08SPaolo Bonzini 
object_release_link_property(Object * obj,const char * name,void * opaque)19759561fda8SStefan Hajnoczi static void object_release_link_property(Object *obj, const char *name,
19769561fda8SStefan Hajnoczi                                          void *opaque)
19779561fda8SStefan Hajnoczi {
19789561fda8SStefan Hajnoczi     LinkProperty *prop = opaque;
19799941d37bSMarc-André Lureau     Object **targetp = object_link_get_targetp(obj, prop);
19809561fda8SStefan Hajnoczi 
19819941d37bSMarc-André Lureau     if ((prop->flags & OBJ_PROP_LINK_STRONG) && *targetp) {
19829941d37bSMarc-André Lureau         object_unref(*targetp);
19839561fda8SStefan Hajnoczi     }
1984840ecdfbSMarc-André Lureau     if (!(prop->flags & OBJ_PROP_LINK_CLASS)) {
19859561fda8SStefan Hajnoczi         g_free(prop);
19869561fda8SStefan Hajnoczi     }
1987840ecdfbSMarc-André Lureau }
19889561fda8SStefan Hajnoczi 
198970251887SMarkus 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)199070251887SMarkus Armbruster object_add_link_prop(Object *obj, const char *name,
19914a8d5798SMarc-André Lureau                      const char *type, void *ptr,
19928f5d58efSIgor Mammedov                      void (*check)(const Object *, const char *,
199339f72ef9SStefan Hajnoczi                                    Object *, Error **),
1994d2623129SMarkus Armbruster                      ObjectPropertyLinkFlags flags)
199557c9fafeSAnthony Liguori {
19969561fda8SStefan Hajnoczi     LinkProperty *prop = g_malloc(sizeof(*prop));
199770251887SMarkus Armbruster     g_autofree char *full_type = NULL;
199864607d08SPaolo Bonzini     ObjectProperty *op;
199957c9fafeSAnthony Liguori 
20004a8d5798SMarc-André Lureau     if (flags & OBJ_PROP_LINK_DIRECT) {
20014a8d5798SMarc-André Lureau         prop->target = ptr;
20024a8d5798SMarc-André Lureau     } else {
20034a8d5798SMarc-André Lureau         prop->targetp = ptr;
20044a8d5798SMarc-André Lureau     }
200539f72ef9SStefan Hajnoczi     prop->check = check;
20069561fda8SStefan Hajnoczi     prop->flags = flags;
20079561fda8SStefan Hajnoczi 
200857c9fafeSAnthony Liguori     full_type = g_strdup_printf("link<%s>", type);
200957c9fafeSAnthony Liguori 
201064607d08SPaolo Bonzini     op = object_property_add(obj, name, full_type,
201157c9fafeSAnthony Liguori                              object_get_link_property,
201239f72ef9SStefan Hajnoczi                              check ? object_set_link_property : NULL,
20139561fda8SStefan Hajnoczi                              object_release_link_property,
2014d2623129SMarkus Armbruster                              prop);
201564607d08SPaolo Bonzini     op->resolve = object_resolve_link_property;
201670251887SMarkus Armbruster     return op;
201757c9fafeSAnthony Liguori }
201857c9fafeSAnthony Liguori 
201970251887SMarkus 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)202070251887SMarkus Armbruster object_property_add_link(Object *obj, const char *name,
20214a8d5798SMarc-André Lureau                          const char *type, Object **targetp,
20224a8d5798SMarc-André Lureau                          void (*check)(const Object *, const char *,
20234a8d5798SMarc-André Lureau                                        Object *, Error **),
2024d2623129SMarkus Armbruster                          ObjectPropertyLinkFlags flags)
20254a8d5798SMarc-André Lureau {
2026d2623129SMarkus Armbruster     return object_add_link_prop(obj, name, type, targetp, check, flags);
20274a8d5798SMarc-André Lureau }
20284a8d5798SMarc-André Lureau 
2029840ecdfbSMarc-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)2030840ecdfbSMarc-André Lureau object_class_property_add_link(ObjectClass *oc,
2031840ecdfbSMarc-André Lureau     const char *name,
2032840ecdfbSMarc-André Lureau     const char *type, ptrdiff_t offset,
2033840ecdfbSMarc-André Lureau     void (*check)(const Object *obj, const char *name,
2034840ecdfbSMarc-André Lureau                   Object *val, Error **errp),
2035d2623129SMarkus Armbruster     ObjectPropertyLinkFlags flags)
2036840ecdfbSMarc-André Lureau {
2037840ecdfbSMarc-André Lureau     LinkProperty *prop = g_new0(LinkProperty, 1);
2038ddfb0baaSMarkus Armbruster     char *full_type;
2039840ecdfbSMarc-André Lureau     ObjectProperty *op;
2040840ecdfbSMarc-André Lureau 
2041840ecdfbSMarc-André Lureau     prop->offset = offset;
2042840ecdfbSMarc-André Lureau     prop->check = check;
2043840ecdfbSMarc-André Lureau     prop->flags = flags | OBJ_PROP_LINK_CLASS;
2044840ecdfbSMarc-André Lureau 
2045840ecdfbSMarc-André Lureau     full_type = g_strdup_printf("link<%s>", type);
2046840ecdfbSMarc-André Lureau 
2047840ecdfbSMarc-André Lureau     op = object_class_property_add(oc, name, full_type,
2048840ecdfbSMarc-André Lureau                                    object_get_link_property,
2049840ecdfbSMarc-André Lureau                                    check ? object_set_link_property : NULL,
2050840ecdfbSMarc-André Lureau                                    object_release_link_property,
2051d2623129SMarkus Armbruster                                    prop);
2052840ecdfbSMarc-André Lureau 
2053840ecdfbSMarc-André Lureau     op->resolve = object_resolve_link_property;
2054840ecdfbSMarc-André Lureau 
2055840ecdfbSMarc-André Lureau     g_free(full_type);
2056840ecdfbSMarc-André Lureau     return op;
2057840ecdfbSMarc-André Lureau }
2058840ecdfbSMarc-André Lureau 
205970251887SMarkus Armbruster ObjectProperty *
object_property_add_const_link(Object * obj,const char * name,Object * target)206070251887SMarkus Armbruster object_property_add_const_link(Object *obj, const char *name,
2061d2623129SMarkus Armbruster                                Object *target)
2062fb9e7e33SPaolo Bonzini {
206370251887SMarkus Armbruster     return object_add_link_prop(obj, name,
206470251887SMarkus Armbruster                                 object_get_typename(target), target,
2065d2623129SMarkus Armbruster                                 NULL, OBJ_PROP_LINK_DIRECT);
2066fb9e7e33SPaolo Bonzini }
2067fb9e7e33SPaolo Bonzini 
object_get_canonical_path_component(const Object * obj)20687a309cc9SMarkus Armbruster const char *object_get_canonical_path_component(const Object *obj)
206957c9fafeSAnthony Liguori {
207057c9fafeSAnthony Liguori     ObjectProperty *prop = NULL;
2071b604a854SPavel Fedin     GHashTableIter iter;
207257c9fafeSAnthony Liguori 
2073770dec26SPaolo Bonzini     if (obj->parent == NULL) {
2074770dec26SPaolo Bonzini         return NULL;
2075770dec26SPaolo Bonzini     }
207657c9fafeSAnthony Liguori 
2077b604a854SPavel Fedin     g_hash_table_iter_init(&iter, obj->parent->properties);
2078b604a854SPavel Fedin     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
20795d9d3f47SAndreas Färber         if (!object_property_is_child(prop)) {
208057c9fafeSAnthony Liguori             continue;
208157c9fafeSAnthony Liguori         }
208257c9fafeSAnthony Liguori 
208357c9fafeSAnthony Liguori         if (prop->opaque == obj) {
20847a309cc9SMarkus Armbruster             return prop->name;
208557c9fafeSAnthony Liguori         }
208657c9fafeSAnthony Liguori     }
208757c9fafeSAnthony Liguori 
208811f590b1SStefan Hajnoczi     /* obj had a parent but was not a child, should never happen */
208911f590b1SStefan Hajnoczi     g_assert_not_reached();
209011f590b1SStefan Hajnoczi     return NULL;
209111f590b1SStefan Hajnoczi }
209211f590b1SStefan Hajnoczi 
object_get_canonical_path(const Object * obj)2093e8512dfaSMarkus Armbruster char *object_get_canonical_path(const Object *obj)
209411f590b1SStefan Hajnoczi {
209511f590b1SStefan Hajnoczi     Object *root = object_get_root();
209611f590b1SStefan Hajnoczi     char *newpath, *path = NULL;
209711f590b1SStefan Hajnoczi 
2098e40077fdSPaolo Bonzini     if (obj == root) {
2099e40077fdSPaolo Bonzini         return g_strdup("/");
2100e40077fdSPaolo Bonzini     }
2101e40077fdSPaolo Bonzini 
2102e40077fdSPaolo Bonzini     do {
21037a309cc9SMarkus Armbruster         const char *component = object_get_canonical_path_component(obj);
210411f590b1SStefan Hajnoczi 
2105e40077fdSPaolo Bonzini         if (!component) {
2106e40077fdSPaolo Bonzini             /* A canonical path must be complete, so discard what was
2107e40077fdSPaolo Bonzini              * collected so far.
2108e40077fdSPaolo Bonzini              */
2109e40077fdSPaolo Bonzini             g_free(path);
2110e40077fdSPaolo Bonzini             return NULL;
2111e40077fdSPaolo Bonzini         }
2112e40077fdSPaolo Bonzini 
2113e40077fdSPaolo Bonzini         newpath = g_strdup_printf("/%s%s", component, path ? path : "");
2114e40077fdSPaolo Bonzini         g_free(path);
211511f590b1SStefan Hajnoczi         path = newpath;
211657c9fafeSAnthony Liguori         obj = obj->parent;
2117e40077fdSPaolo Bonzini     } while (obj != root);
211857c9fafeSAnthony Liguori 
2119e40077fdSPaolo Bonzini     return path;
212057c9fafeSAnthony Liguori }
212157c9fafeSAnthony Liguori 
object_resolve_path_component(Object * parent,const char * part)2122ddfb0baaSMarkus Armbruster Object *object_resolve_path_component(Object *parent, const char *part)
2123a612b2a6SPaolo Bonzini {
2124efba1595SDaniel P. Berrangé     ObjectProperty *prop = object_property_find(parent, part);
2125a612b2a6SPaolo Bonzini     if (prop == NULL) {
2126a612b2a6SPaolo Bonzini         return NULL;
2127a612b2a6SPaolo Bonzini     }
2128a612b2a6SPaolo Bonzini 
212964607d08SPaolo Bonzini     if (prop->resolve) {
213064607d08SPaolo Bonzini         return prop->resolve(parent, prop->opaque, part);
2131a612b2a6SPaolo Bonzini     } else {
2132a612b2a6SPaolo Bonzini         return NULL;
2133a612b2a6SPaolo Bonzini     }
2134a612b2a6SPaolo Bonzini }
2135a612b2a6SPaolo Bonzini 
object_resolve_abs_path(Object * parent,char ** parts,const char * typename)213657c9fafeSAnthony Liguori static Object *object_resolve_abs_path(Object *parent,
2137ddfb0baaSMarkus Armbruster                                           char **parts,
2138ad195c8fSMasahiro Yamada                                           const char *typename)
213957c9fafeSAnthony Liguori {
214057c9fafeSAnthony Liguori     Object *child;
214157c9fafeSAnthony Liguori 
2142ad195c8fSMasahiro Yamada     if (*parts == NULL) {
214302fe2db6SPaolo Bonzini         return object_dynamic_cast(parent, typename);
214457c9fafeSAnthony Liguori     }
214557c9fafeSAnthony Liguori 
2146ad195c8fSMasahiro Yamada     if (strcmp(*parts, "") == 0) {
2147ad195c8fSMasahiro Yamada         return object_resolve_abs_path(parent, parts + 1, typename);
214857c9fafeSAnthony Liguori     }
214957c9fafeSAnthony Liguori 
2150ad195c8fSMasahiro Yamada     child = object_resolve_path_component(parent, *parts);
215157c9fafeSAnthony Liguori     if (!child) {
215257c9fafeSAnthony Liguori         return NULL;
215357c9fafeSAnthony Liguori     }
215457c9fafeSAnthony Liguori 
2155ad195c8fSMasahiro Yamada     return object_resolve_abs_path(child, parts + 1, typename);
215657c9fafeSAnthony Liguori }
215757c9fafeSAnthony Liguori 
object_resolve_partial_path(Object * parent,char ** parts,const char * typename,bool * ambiguous)215857c9fafeSAnthony Liguori static Object *object_resolve_partial_path(Object *parent,
2159ddfb0baaSMarkus Armbruster                                            char **parts,
216002fe2db6SPaolo Bonzini                                            const char *typename,
216157c9fafeSAnthony Liguori                                            bool *ambiguous)
216257c9fafeSAnthony Liguori {
216357c9fafeSAnthony Liguori     Object *obj;
2164b604a854SPavel Fedin     GHashTableIter iter;
216557c9fafeSAnthony Liguori     ObjectProperty *prop;
216657c9fafeSAnthony Liguori 
2167ad195c8fSMasahiro Yamada     obj = object_resolve_abs_path(parent, parts, typename);
216857c9fafeSAnthony Liguori 
2169b604a854SPavel Fedin     g_hash_table_iter_init(&iter, parent->properties);
2170b604a854SPavel Fedin     while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
217157c9fafeSAnthony Liguori         Object *found;
217257c9fafeSAnthony Liguori 
21735d9d3f47SAndreas Färber         if (!object_property_is_child(prop)) {
217457c9fafeSAnthony Liguori             continue;
217557c9fafeSAnthony Liguori         }
217657c9fafeSAnthony Liguori 
217702fe2db6SPaolo Bonzini         found = object_resolve_partial_path(prop->opaque, parts,
217802fe2db6SPaolo Bonzini                                             typename, ambiguous);
217957c9fafeSAnthony Liguori         if (found) {
218057c9fafeSAnthony Liguori             if (obj) {
218157c9fafeSAnthony Liguori                 *ambiguous = true;
218257c9fafeSAnthony Liguori                 return NULL;
218357c9fafeSAnthony Liguori             }
218457c9fafeSAnthony Liguori             obj = found;
218557c9fafeSAnthony Liguori         }
218657c9fafeSAnthony Liguori 
2187ebcc479eSEduardo Habkost         if (*ambiguous) {
218857c9fafeSAnthony Liguori             return NULL;
218957c9fafeSAnthony Liguori         }
219057c9fafeSAnthony Liguori     }
219157c9fafeSAnthony Liguori 
219257c9fafeSAnthony Liguori     return obj;
219357c9fafeSAnthony Liguori }
219457c9fafeSAnthony Liguori 
object_resolve_path_type(const char * path,const char * typename,bool * ambiguousp)219502fe2db6SPaolo Bonzini Object *object_resolve_path_type(const char *path, const char *typename,
2196ebcc479eSEduardo Habkost                                  bool *ambiguousp)
219757c9fafeSAnthony Liguori {
219857c9fafeSAnthony Liguori     Object *obj;
2199ddfb0baaSMarkus Armbruster     char **parts;
220057c9fafeSAnthony Liguori 
220157c9fafeSAnthony Liguori     parts = g_strsplit(path, "/", 0);
22022e1103f6SPaolo Bonzini     assert(parts);
220357c9fafeSAnthony Liguori 
22042e1103f6SPaolo Bonzini     if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
2205ebcc479eSEduardo Habkost         bool ambiguous = false;
220602fe2db6SPaolo Bonzini         obj = object_resolve_partial_path(object_get_root(), parts,
2207ebcc479eSEduardo Habkost                                           typename, &ambiguous);
2208ebcc479eSEduardo Habkost         if (ambiguousp) {
2209ebcc479eSEduardo Habkost             *ambiguousp = ambiguous;
2210ebcc479eSEduardo Habkost         }
221157c9fafeSAnthony Liguori     } else {
2212ad195c8fSMasahiro Yamada         obj = object_resolve_abs_path(object_get_root(), parts + 1, typename);
221357c9fafeSAnthony Liguori     }
221457c9fafeSAnthony Liguori 
221557c9fafeSAnthony Liguori     g_strfreev(parts);
221657c9fafeSAnthony Liguori 
221757c9fafeSAnthony Liguori     return obj;
221857c9fafeSAnthony Liguori }
221957c9fafeSAnthony Liguori 
object_resolve_path(const char * path,bool * ambiguous)222002fe2db6SPaolo Bonzini Object *object_resolve_path(const char *path, bool *ambiguous)
222102fe2db6SPaolo Bonzini {
222202fe2db6SPaolo Bonzini     return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
222302fe2db6SPaolo Bonzini }
222402fe2db6SPaolo Bonzini 
object_resolve_path_at(Object * parent,const char * path)22251bf4d329SMarkus Armbruster Object *object_resolve_path_at(Object *parent, const char *path)
22261bf4d329SMarkus Armbruster {
22271bf4d329SMarkus Armbruster     g_auto(GStrv) parts = g_strsplit(path, "/", 0);
22281bf4d329SMarkus Armbruster 
22291bf4d329SMarkus Armbruster     if (*path == '/') {
22301bf4d329SMarkus Armbruster         return object_resolve_abs_path(object_get_root(), parts + 1,
22311bf4d329SMarkus Armbruster                                        TYPE_OBJECT);
22321bf4d329SMarkus Armbruster     }
22331bf4d329SMarkus Armbruster     return object_resolve_abs_path(parent, parts, TYPE_OBJECT);
22341bf4d329SMarkus Armbruster }
22351bf4d329SMarkus Armbruster 
object_resolve_type_unambiguous(const char * typename,Error ** errp)2236ee3b34cdSPaolo Bonzini Object *object_resolve_type_unambiguous(const char *typename, Error **errp)
2237ee3b34cdSPaolo Bonzini {
2238ee3b34cdSPaolo Bonzini     bool ambig;
2239ee3b34cdSPaolo Bonzini     Object *o = object_resolve_path_type("", typename, &ambig);
2240ee3b34cdSPaolo Bonzini 
2241ee3b34cdSPaolo Bonzini     if (ambig) {
2242ee3b34cdSPaolo Bonzini         error_setg(errp, "More than one object of type %s", typename);
2243ee3b34cdSPaolo Bonzini         return NULL;
2244ee3b34cdSPaolo Bonzini     }
2245ee3b34cdSPaolo Bonzini     if (!o) {
2246ee3b34cdSPaolo Bonzini         error_setg(errp, "No object found of type %s", typename);
2247ee3b34cdSPaolo Bonzini         return NULL;
2248ee3b34cdSPaolo Bonzini     }
2249ee3b34cdSPaolo Bonzini     return o;
2250ee3b34cdSPaolo Bonzini }
2251ee3b34cdSPaolo Bonzini 
225257c9fafeSAnthony Liguori typedef struct StringProperty
225357c9fafeSAnthony Liguori {
225457c9fafeSAnthony Liguori     char *(*get)(Object *, Error **);
225557c9fafeSAnthony Liguori     void (*set)(Object *, const char *, Error **);
225657c9fafeSAnthony Liguori } StringProperty;
225757c9fafeSAnthony Liguori 
property_get_str(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2258d7bce999SEric Blake static void property_get_str(Object *obj, Visitor *v, const char *name,
2259d7bce999SEric Blake                              void *opaque, Error **errp)
226057c9fafeSAnthony Liguori {
226157c9fafeSAnthony Liguori     StringProperty *prop = opaque;
226257c9fafeSAnthony Liguori     char *value;
2263e1c8237dSMarkus Armbruster     Error *err = NULL;
226457c9fafeSAnthony Liguori 
2265e1c8237dSMarkus Armbruster     value = prop->get(obj, &err);
2266e1c8237dSMarkus Armbruster     if (err) {
2267e1c8237dSMarkus Armbruster         error_propagate(errp, err);
2268e1c8237dSMarkus Armbruster         return;
2269e1c8237dSMarkus Armbruster     }
2270e1c8237dSMarkus Armbruster 
227151e72bc1SEric Blake     visit_type_str(v, name, &value, errp);
227257c9fafeSAnthony Liguori     g_free(value);
227357c9fafeSAnthony Liguori }
227457c9fafeSAnthony Liguori 
property_set_str(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2275d7bce999SEric Blake static void property_set_str(Object *obj, Visitor *v, const char *name,
2276d7bce999SEric Blake                              void *opaque, Error **errp)
227757c9fafeSAnthony Liguori {
227857c9fafeSAnthony Liguori     StringProperty *prop = opaque;
227957c9fafeSAnthony Liguori     char *value;
228057c9fafeSAnthony Liguori 
2281668f62ecSMarkus Armbruster     if (!visit_type_str(v, name, &value, errp)) {
228257c9fafeSAnthony Liguori         return;
228357c9fafeSAnthony Liguori     }
228457c9fafeSAnthony Liguori 
228557c9fafeSAnthony Liguori     prop->set(obj, value, errp);
228657c9fafeSAnthony Liguori     g_free(value);
228757c9fafeSAnthony Liguori }
228857c9fafeSAnthony Liguori 
property_release_data(Object * obj,const char * name,void * opaque)2289169cbac1SPaolo Bonzini static void property_release_data(Object *obj, const char *name,
229057c9fafeSAnthony Liguori                                   void *opaque)
229157c9fafeSAnthony Liguori {
2292169cbac1SPaolo Bonzini     g_free(opaque);
229357c9fafeSAnthony Liguori }
229457c9fafeSAnthony Liguori 
229570251887SMarkus Armbruster ObjectProperty *
object_property_add_str(Object * obj,const char * name,char * (* get)(Object *,Error **),void (* set)(Object *,const char *,Error **))229670251887SMarkus Armbruster object_property_add_str(Object *obj, const char *name,
229757c9fafeSAnthony Liguori                         char *(*get)(Object *, Error **),
2298d2623129SMarkus Armbruster                         void (*set)(Object *, const char *, Error **))
229957c9fafeSAnthony Liguori {
230057c9fafeSAnthony Liguori     StringProperty *prop = g_malloc0(sizeof(*prop));
230157c9fafeSAnthony Liguori 
230257c9fafeSAnthony Liguori     prop->get = get;
230357c9fafeSAnthony Liguori     prop->set = set;
230457c9fafeSAnthony Liguori 
2305d2623129SMarkus Armbruster     return object_property_add(obj, name, "string",
23067b7b7d18SPaolo Bonzini                                get ? property_get_str : NULL,
23077b7b7d18SPaolo Bonzini                                set ? property_set_str : NULL,
2308169cbac1SPaolo Bonzini                                property_release_data,
2309d2623129SMarkus Armbruster                                prop);
231057c9fafeSAnthony Liguori }
2311745549c8SPaolo Bonzini 
2312a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_str(ObjectClass * klass,const char * name,char * (* get)(Object *,Error **),void (* set)(Object *,const char *,Error **))2313a3a16211SMarc-André Lureau object_class_property_add_str(ObjectClass *klass, const char *name,
231416bf7f52SDaniel P. Berrange                                    char *(*get)(Object *, Error **),
231516bf7f52SDaniel P. Berrange                                    void (*set)(Object *, const char *,
2316d2623129SMarkus Armbruster                                                Error **))
231716bf7f52SDaniel P. Berrange {
231816bf7f52SDaniel P. Berrange     StringProperty *prop = g_malloc0(sizeof(*prop));
231916bf7f52SDaniel P. Berrange 
232016bf7f52SDaniel P. Berrange     prop->get = get;
232116bf7f52SDaniel P. Berrange     prop->set = set;
232216bf7f52SDaniel P. Berrange 
2323d2623129SMarkus Armbruster     return object_class_property_add(klass, name, "string",
232416bf7f52SDaniel P. Berrange                                      get ? property_get_str : NULL,
232516bf7f52SDaniel P. Berrange                                      set ? property_set_str : NULL,
2326fc4fe712SMarc-André Lureau                                      NULL,
2327d2623129SMarkus Armbruster                                      prop);
232816bf7f52SDaniel P. Berrange }
232916bf7f52SDaniel P. Berrange 
23300e558843SAnthony Liguori typedef struct BoolProperty
23310e558843SAnthony Liguori {
23320e558843SAnthony Liguori     bool (*get)(Object *, Error **);
23330e558843SAnthony Liguori     void (*set)(Object *, bool, Error **);
23340e558843SAnthony Liguori } BoolProperty;
23350e558843SAnthony Liguori 
property_get_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2336d7bce999SEric Blake static void property_get_bool(Object *obj, Visitor *v, const char *name,
2337d7bce999SEric Blake                               void *opaque, Error **errp)
23380e558843SAnthony Liguori {
23390e558843SAnthony Liguori     BoolProperty *prop = opaque;
23400e558843SAnthony Liguori     bool value;
23414715d42eSMarkus Armbruster     Error *err = NULL;
23420e558843SAnthony Liguori 
23434715d42eSMarkus Armbruster     value = prop->get(obj, &err);
23444715d42eSMarkus Armbruster     if (err) {
23454715d42eSMarkus Armbruster         error_propagate(errp, err);
23464715d42eSMarkus Armbruster         return;
23474715d42eSMarkus Armbruster     }
23484715d42eSMarkus Armbruster 
234951e72bc1SEric Blake     visit_type_bool(v, name, &value, errp);
23500e558843SAnthony Liguori }
23510e558843SAnthony Liguori 
property_set_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2352d7bce999SEric Blake static void property_set_bool(Object *obj, Visitor *v, const char *name,
2353d7bce999SEric Blake                               void *opaque, Error **errp)
23540e558843SAnthony Liguori {
23550e558843SAnthony Liguori     BoolProperty *prop = opaque;
23560e558843SAnthony Liguori     bool value;
23570e558843SAnthony Liguori 
2358668f62ecSMarkus Armbruster     if (!visit_type_bool(v, name, &value, errp)) {
23590e558843SAnthony Liguori         return;
23600e558843SAnthony Liguori     }
23610e558843SAnthony Liguori 
23620e558843SAnthony Liguori     prop->set(obj, value, errp);
23630e558843SAnthony Liguori }
23640e558843SAnthony Liguori 
236570251887SMarkus Armbruster ObjectProperty *
object_property_add_bool(Object * obj,const char * name,bool (* get)(Object *,Error **),void (* set)(Object *,bool,Error **))236670251887SMarkus Armbruster object_property_add_bool(Object *obj, const char *name,
23670e558843SAnthony Liguori                          bool (*get)(Object *, Error **),
2368d2623129SMarkus Armbruster                          void (*set)(Object *, bool, Error **))
23690e558843SAnthony Liguori {
23700e558843SAnthony Liguori     BoolProperty *prop = g_malloc0(sizeof(*prop));
23710e558843SAnthony Liguori 
23720e558843SAnthony Liguori     prop->get = get;
23730e558843SAnthony Liguori     prop->set = set;
23740e558843SAnthony Liguori 
2375d2623129SMarkus Armbruster     return object_property_add(obj, name, "bool",
23760e558843SAnthony Liguori                                get ? property_get_bool : NULL,
23770e558843SAnthony Liguori                                set ? property_set_bool : NULL,
2378169cbac1SPaolo Bonzini                                property_release_data,
2379d2623129SMarkus Armbruster                                prop);
23800e558843SAnthony Liguori }
23810e558843SAnthony Liguori 
2382a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_bool(ObjectClass * klass,const char * name,bool (* get)(Object *,Error **),void (* set)(Object *,bool,Error **))2383a3a16211SMarc-André Lureau object_class_property_add_bool(ObjectClass *klass, const char *name,
238416bf7f52SDaniel P. Berrange                                     bool (*get)(Object *, Error **),
2385d2623129SMarkus Armbruster                                     void (*set)(Object *, bool, Error **))
238616bf7f52SDaniel P. Berrange {
238716bf7f52SDaniel P. Berrange     BoolProperty *prop = g_malloc0(sizeof(*prop));
238816bf7f52SDaniel P. Berrange 
238916bf7f52SDaniel P. Berrange     prop->get = get;
239016bf7f52SDaniel P. Berrange     prop->set = set;
239116bf7f52SDaniel P. Berrange 
2392d2623129SMarkus Armbruster     return object_class_property_add(klass, name, "bool",
239316bf7f52SDaniel P. Berrange                                      get ? property_get_bool : NULL,
239416bf7f52SDaniel P. Berrange                                      set ? property_set_bool : NULL,
2395fc4fe712SMarc-André Lureau                                      NULL,
2396d2623129SMarkus Armbruster                                      prop);
239716bf7f52SDaniel P. Berrange }
239816bf7f52SDaniel P. Berrange 
property_get_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2399d7bce999SEric Blake static void property_get_enum(Object *obj, Visitor *v, const char *name,
2400d7bce999SEric Blake                               void *opaque, Error **errp)
2401a8e3fbedSDaniel P. Berrange {
2402a8e3fbedSDaniel P. Berrange     EnumProperty *prop = opaque;
2403a8e3fbedSDaniel P. Berrange     int value;
24044715d42eSMarkus Armbruster     Error *err = NULL;
2405a8e3fbedSDaniel P. Berrange 
24064715d42eSMarkus Armbruster     value = prop->get(obj, &err);
24074715d42eSMarkus Armbruster     if (err) {
24084715d42eSMarkus Armbruster         error_propagate(errp, err);
24094715d42eSMarkus Armbruster         return;
24104715d42eSMarkus Armbruster     }
24114715d42eSMarkus Armbruster 
2412f7abe0ecSMarc-André Lureau     visit_type_enum(v, name, &value, prop->lookup, errp);
2413a8e3fbedSDaniel P. Berrange }
2414a8e3fbedSDaniel P. Berrange 
property_set_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2415d7bce999SEric Blake static void property_set_enum(Object *obj, Visitor *v, const char *name,
2416d7bce999SEric Blake                               void *opaque, Error **errp)
2417a8e3fbedSDaniel P. Berrange {
2418a8e3fbedSDaniel P. Berrange     EnumProperty *prop = opaque;
2419a8e3fbedSDaniel P. Berrange     int value;
2420a8e3fbedSDaniel P. Berrange 
2421668f62ecSMarkus Armbruster     if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
24224715d42eSMarkus Armbruster         return;
24234715d42eSMarkus Armbruster     }
2424a8e3fbedSDaniel P. Berrange     prop->set(obj, value, errp);
2425a8e3fbedSDaniel P. Berrange }
2426a8e3fbedSDaniel P. Berrange 
242770251887SMarkus 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 **))242870251887SMarkus Armbruster object_property_add_enum(Object *obj, const char *name,
2429a8e3fbedSDaniel P. Berrange                          const char *typename,
2430f7abe0ecSMarc-André Lureau                          const QEnumLookup *lookup,
2431a8e3fbedSDaniel P. Berrange                          int (*get)(Object *, Error **),
2432d2623129SMarkus Armbruster                          void (*set)(Object *, int, Error **))
2433a8e3fbedSDaniel P. Berrange {
2434a8e3fbedSDaniel P. Berrange     EnumProperty *prop = g_malloc(sizeof(*prop));
2435a8e3fbedSDaniel P. Berrange 
2436f7abe0ecSMarc-André Lureau     prop->lookup = lookup;
2437a8e3fbedSDaniel P. Berrange     prop->get = get;
2438a8e3fbedSDaniel P. Berrange     prop->set = set;
2439a8e3fbedSDaniel P. Berrange 
2440d2623129SMarkus Armbruster     return object_property_add(obj, name, typename,
2441a8e3fbedSDaniel P. Berrange                                get ? property_get_enum : NULL,
2442a8e3fbedSDaniel P. Berrange                                set ? property_set_enum : NULL,
2443169cbac1SPaolo Bonzini                                property_release_data,
2444d2623129SMarkus Armbruster                                prop);
2445a8e3fbedSDaniel P. Berrange }
2446a8e3fbedSDaniel P. Berrange 
2447a3a16211SMarc-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 **))2448a3a16211SMarc-André Lureau object_class_property_add_enum(ObjectClass *klass, const char *name,
244916bf7f52SDaniel P. Berrange                                     const char *typename,
2450f7abe0ecSMarc-André Lureau                                     const QEnumLookup *lookup,
245116bf7f52SDaniel P. Berrange                                     int (*get)(Object *, Error **),
2452d2623129SMarkus Armbruster                                     void (*set)(Object *, int, Error **))
245316bf7f52SDaniel P. Berrange {
245416bf7f52SDaniel P. Berrange     EnumProperty *prop = g_malloc(sizeof(*prop));
245516bf7f52SDaniel P. Berrange 
2456f7abe0ecSMarc-André Lureau     prop->lookup = lookup;
245716bf7f52SDaniel P. Berrange     prop->get = get;
245816bf7f52SDaniel P. Berrange     prop->set = set;
245916bf7f52SDaniel P. Berrange 
2460d2623129SMarkus Armbruster     return object_class_property_add(klass, name, typename,
246116bf7f52SDaniel P. Berrange                                      get ? property_get_enum : NULL,
246216bf7f52SDaniel P. Berrange                                      set ? property_set_enum : NULL,
2463fc4fe712SMarc-André Lureau                                      NULL,
2464d2623129SMarkus Armbruster                                      prop);
246516bf7f52SDaniel P. Berrange }
246616bf7f52SDaniel P. Berrange 
24678e099d14SDavid Gibson typedef struct TMProperty {
24688e099d14SDavid Gibson     void (*get)(Object *, struct tm *, Error **);
24698e099d14SDavid Gibson } TMProperty;
24708e099d14SDavid Gibson 
property_get_tm(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2471d7bce999SEric Blake static void property_get_tm(Object *obj, Visitor *v, const char *name,
2472d7bce999SEric Blake                             void *opaque, Error **errp)
24738e099d14SDavid Gibson {
24748e099d14SDavid Gibson     TMProperty *prop = opaque;
24758e099d14SDavid Gibson     Error *err = NULL;
24768e099d14SDavid Gibson     struct tm value;
24778e099d14SDavid Gibson 
24788e099d14SDavid Gibson     prop->get(obj, &value, &err);
24798e099d14SDavid Gibson     if (err) {
2480992861fbSMarkus Armbruster         error_propagate(errp, err);
2481992861fbSMarkus Armbruster         return;
24828e099d14SDavid Gibson     }
24838e099d14SDavid Gibson 
2484992861fbSMarkus Armbruster     if (!visit_start_struct(v, name, NULL, 0, errp)) {
2485992861fbSMarkus Armbruster         return;
24868e099d14SDavid Gibson     }
2487992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_year", &value.tm_year, errp)) {
24888e099d14SDavid Gibson         goto out_end;
24898e099d14SDavid Gibson     }
2490992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_mon", &value.tm_mon, errp)) {
24918e099d14SDavid Gibson         goto out_end;
24928e099d14SDavid Gibson     }
2493992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_mday", &value.tm_mday, errp)) {
24948e099d14SDavid Gibson         goto out_end;
24958e099d14SDavid Gibson     }
2496992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_hour", &value.tm_hour, errp)) {
24978e099d14SDavid Gibson         goto out_end;
24988e099d14SDavid Gibson     }
2499992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_min", &value.tm_min, errp)) {
25008e099d14SDavid Gibson         goto out_end;
25018e099d14SDavid Gibson     }
2502992861fbSMarkus Armbruster     if (!visit_type_int32(v, "tm_sec", &value.tm_sec, errp)) {
25038e099d14SDavid Gibson         goto out_end;
25048e099d14SDavid Gibson     }
2505992861fbSMarkus Armbruster     visit_check_struct(v, errp);
25068e099d14SDavid Gibson out_end:
25071158bb2aSEric Blake     visit_end_struct(v, NULL);
25088e099d14SDavid Gibson }
25098e099d14SDavid Gibson 
251070251887SMarkus Armbruster ObjectProperty *
object_property_add_tm(Object * obj,const char * name,void (* get)(Object *,struct tm *,Error **))251170251887SMarkus Armbruster object_property_add_tm(Object *obj, const char *name,
2512d2623129SMarkus Armbruster                        void (*get)(Object *, struct tm *, Error **))
25138e099d14SDavid Gibson {
25148e099d14SDavid Gibson     TMProperty *prop = g_malloc0(sizeof(*prop));
25158e099d14SDavid Gibson 
25168e099d14SDavid Gibson     prop->get = get;
25178e099d14SDavid Gibson 
2518d2623129SMarkus Armbruster     return object_property_add(obj, name, "struct tm",
25198e099d14SDavid Gibson                                get ? property_get_tm : NULL, NULL,
2520169cbac1SPaolo Bonzini                                property_release_data,
2521d2623129SMarkus Armbruster                                prop);
25228e099d14SDavid Gibson }
25238e099d14SDavid Gibson 
2524a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_tm(ObjectClass * klass,const char * name,void (* get)(Object *,struct tm *,Error **))2525a3a16211SMarc-André Lureau object_class_property_add_tm(ObjectClass *klass, const char *name,
2526d2623129SMarkus Armbruster                              void (*get)(Object *, struct tm *, Error **))
252716bf7f52SDaniel P. Berrange {
252816bf7f52SDaniel P. Berrange     TMProperty *prop = g_malloc0(sizeof(*prop));
252916bf7f52SDaniel P. Berrange 
253016bf7f52SDaniel P. Berrange     prop->get = get;
253116bf7f52SDaniel P. Berrange 
2532d2623129SMarkus Armbruster     return object_class_property_add(klass, name, "struct tm",
2533d2623129SMarkus Armbruster                                      get ? property_get_tm : NULL,
2534d2623129SMarkus Armbruster                                      NULL, NULL, prop);
253516bf7f52SDaniel P. Berrange }
253616bf7f52SDaniel P. Berrange 
object_get_type(Object * obj,Error ** errp)253790c69fb9SMarkus Armbruster static char *object_get_type(Object *obj, Error **errp)
25382f262e06SPaolo Bonzini {
25392f262e06SPaolo Bonzini     return g_strdup(object_get_typename(obj));
25402f262e06SPaolo Bonzini }
25412f262e06SPaolo Bonzini 
property_get_uint8_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2542d7bce999SEric Blake static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2543d7bce999SEric Blake                                    void *opaque, Error **errp)
2544e732ea63SMichael S. Tsirkin {
2545e732ea63SMichael S. Tsirkin     uint8_t value = *(uint8_t *)opaque;
254651e72bc1SEric Blake     visit_type_uint8(v, name, &value, errp);
2547e732ea63SMichael S. Tsirkin }
2548e732ea63SMichael S. Tsirkin 
property_set_uint8_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2549836e1b38SFelipe Franciosi static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
2550836e1b38SFelipe Franciosi                                    void *opaque, Error **errp)
2551836e1b38SFelipe Franciosi {
2552836e1b38SFelipe Franciosi     uint8_t *field = opaque;
2553836e1b38SFelipe Franciosi     uint8_t value;
2554836e1b38SFelipe Franciosi 
2555668f62ecSMarkus Armbruster     if (!visit_type_uint8(v, name, &value, errp)) {
2556836e1b38SFelipe Franciosi         return;
2557836e1b38SFelipe Franciosi     }
2558836e1b38SFelipe Franciosi 
2559836e1b38SFelipe Franciosi     *field = value;
2560836e1b38SFelipe Franciosi }
2561836e1b38SFelipe Franciosi 
property_get_uint16_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2562d7bce999SEric Blake static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2563d7bce999SEric Blake                                     void *opaque, Error **errp)
2564e732ea63SMichael S. Tsirkin {
2565e732ea63SMichael S. Tsirkin     uint16_t value = *(uint16_t *)opaque;
256651e72bc1SEric Blake     visit_type_uint16(v, name, &value, errp);
2567e732ea63SMichael S. Tsirkin }
2568e732ea63SMichael S. Tsirkin 
property_set_uint16_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2569836e1b38SFelipe Franciosi static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
2570836e1b38SFelipe Franciosi                                     void *opaque, Error **errp)
2571836e1b38SFelipe Franciosi {
2572836e1b38SFelipe Franciosi     uint16_t *field = opaque;
2573836e1b38SFelipe Franciosi     uint16_t value;
2574836e1b38SFelipe Franciosi 
2575668f62ecSMarkus Armbruster     if (!visit_type_uint16(v, name, &value, errp)) {
2576836e1b38SFelipe Franciosi         return;
2577836e1b38SFelipe Franciosi     }
2578836e1b38SFelipe Franciosi 
2579836e1b38SFelipe Franciosi     *field = value;
2580836e1b38SFelipe Franciosi }
2581836e1b38SFelipe Franciosi 
property_get_uint32_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2582d7bce999SEric Blake static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2583d7bce999SEric Blake                                     void *opaque, Error **errp)
2584e732ea63SMichael S. Tsirkin {
2585e732ea63SMichael S. Tsirkin     uint32_t value = *(uint32_t *)opaque;
258651e72bc1SEric Blake     visit_type_uint32(v, name, &value, errp);
2587e732ea63SMichael S. Tsirkin }
2588e732ea63SMichael S. Tsirkin 
property_set_uint32_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2589836e1b38SFelipe Franciosi static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
2590836e1b38SFelipe Franciosi                                     void *opaque, Error **errp)
2591836e1b38SFelipe Franciosi {
2592836e1b38SFelipe Franciosi     uint32_t *field = opaque;
2593836e1b38SFelipe Franciosi     uint32_t value;
2594836e1b38SFelipe Franciosi 
2595668f62ecSMarkus Armbruster     if (!visit_type_uint32(v, name, &value, errp)) {
2596836e1b38SFelipe Franciosi         return;
2597836e1b38SFelipe Franciosi     }
2598836e1b38SFelipe Franciosi 
2599836e1b38SFelipe Franciosi     *field = value;
2600836e1b38SFelipe Franciosi }
2601836e1b38SFelipe Franciosi 
property_get_uint64_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2602d7bce999SEric Blake static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2603d7bce999SEric Blake                                     void *opaque, Error **errp)
2604e732ea63SMichael S. Tsirkin {
2605e732ea63SMichael S. Tsirkin     uint64_t value = *(uint64_t *)opaque;
260651e72bc1SEric Blake     visit_type_uint64(v, name, &value, errp);
2607e732ea63SMichael S. Tsirkin }
2608e732ea63SMichael S. Tsirkin 
property_set_uint64_ptr(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2609836e1b38SFelipe Franciosi static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
2610836e1b38SFelipe Franciosi                                     void *opaque, Error **errp)
2611e732ea63SMichael S. Tsirkin {
2612836e1b38SFelipe Franciosi     uint64_t *field = opaque;
2613836e1b38SFelipe Franciosi     uint64_t value;
2614836e1b38SFelipe Franciosi 
2615668f62ecSMarkus Armbruster     if (!visit_type_uint64(v, name, &value, errp)) {
2616836e1b38SFelipe Franciosi         return;
2617836e1b38SFelipe Franciosi     }
2618836e1b38SFelipe Franciosi 
2619836e1b38SFelipe Franciosi     *field = value;
2620836e1b38SFelipe Franciosi }
2621836e1b38SFelipe Franciosi 
262270251887SMarkus Armbruster ObjectProperty *
object_property_add_uint8_ptr(Object * obj,const char * name,const uint8_t * v,ObjectPropertyFlags flags)262370251887SMarkus Armbruster object_property_add_uint8_ptr(Object *obj, const char *name,
2624836e1b38SFelipe Franciosi                               const uint8_t *v,
2625d2623129SMarkus Armbruster                               ObjectPropertyFlags flags)
2626836e1b38SFelipe Franciosi {
2627836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2628836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2629836e1b38SFelipe Franciosi 
2630836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2631836e1b38SFelipe Franciosi         getter = property_get_uint8_ptr;
2632836e1b38SFelipe Franciosi     }
2633836e1b38SFelipe Franciosi 
2634836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2635836e1b38SFelipe Franciosi         setter = property_set_uint8_ptr;
2636836e1b38SFelipe Franciosi     }
2637836e1b38SFelipe Franciosi 
263870251887SMarkus Armbruster     return object_property_add(obj, name, "uint8",
2639d2623129SMarkus Armbruster                                getter, setter, NULL, (void *)v);
2640e732ea63SMichael S. Tsirkin }
2641e732ea63SMichael S. Tsirkin 
2642a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint8_ptr(ObjectClass * klass,const char * name,const uint8_t * v,ObjectPropertyFlags flags)2643a3a16211SMarc-André Lureau object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2644836e1b38SFelipe Franciosi                                     const uint8_t *v,
2645d2623129SMarkus Armbruster                                     ObjectPropertyFlags flags)
264616bf7f52SDaniel P. Berrange {
2647836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2648836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2649836e1b38SFelipe Franciosi 
2650836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2651836e1b38SFelipe Franciosi         getter = property_get_uint8_ptr;
2652836e1b38SFelipe Franciosi     }
2653836e1b38SFelipe Franciosi 
2654836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2655836e1b38SFelipe Franciosi         setter = property_set_uint8_ptr;
2656836e1b38SFelipe Franciosi     }
2657836e1b38SFelipe Franciosi 
2658a3a16211SMarc-André Lureau     return object_class_property_add(klass, name, "uint8",
2659d2623129SMarkus Armbruster                                      getter, setter, NULL, (void *)v);
266016bf7f52SDaniel P. Berrange }
266116bf7f52SDaniel P. Berrange 
266270251887SMarkus Armbruster ObjectProperty *
object_property_add_uint16_ptr(Object * obj,const char * name,const uint16_t * v,ObjectPropertyFlags flags)266370251887SMarkus Armbruster object_property_add_uint16_ptr(Object *obj, const char *name,
2664836e1b38SFelipe Franciosi                                const uint16_t *v,
2665d2623129SMarkus Armbruster                                ObjectPropertyFlags flags)
2666e732ea63SMichael S. Tsirkin {
2667836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2668836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2669836e1b38SFelipe Franciosi 
2670836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2671836e1b38SFelipe Franciosi         getter = property_get_uint16_ptr;
2672836e1b38SFelipe Franciosi     }
2673836e1b38SFelipe Franciosi 
2674836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2675836e1b38SFelipe Franciosi         setter = property_set_uint16_ptr;
2676836e1b38SFelipe Franciosi     }
2677836e1b38SFelipe Franciosi 
267870251887SMarkus Armbruster     return object_property_add(obj, name, "uint16",
2679d2623129SMarkus Armbruster                                getter, setter, NULL, (void *)v);
2680e732ea63SMichael S. Tsirkin }
2681e732ea63SMichael S. Tsirkin 
2682a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint16_ptr(ObjectClass * klass,const char * name,const uint16_t * v,ObjectPropertyFlags flags)2683a3a16211SMarc-André Lureau object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2684836e1b38SFelipe Franciosi                                      const uint16_t *v,
2685d2623129SMarkus Armbruster                                      ObjectPropertyFlags flags)
268616bf7f52SDaniel P. Berrange {
2687836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2688836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2689836e1b38SFelipe Franciosi 
2690836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2691836e1b38SFelipe Franciosi         getter = property_get_uint16_ptr;
2692836e1b38SFelipe Franciosi     }
2693836e1b38SFelipe Franciosi 
2694836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2695836e1b38SFelipe Franciosi         setter = property_set_uint16_ptr;
2696836e1b38SFelipe Franciosi     }
2697836e1b38SFelipe Franciosi 
2698a3a16211SMarc-André Lureau     return object_class_property_add(klass, name, "uint16",
2699d2623129SMarkus Armbruster                                      getter, setter, NULL, (void *)v);
270016bf7f52SDaniel P. Berrange }
270116bf7f52SDaniel P. Berrange 
270270251887SMarkus Armbruster ObjectProperty *
object_property_add_uint32_ptr(Object * obj,const char * name,const uint32_t * v,ObjectPropertyFlags flags)270370251887SMarkus Armbruster object_property_add_uint32_ptr(Object *obj, const char *name,
2704836e1b38SFelipe Franciosi                                const uint32_t *v,
2705d2623129SMarkus Armbruster                                ObjectPropertyFlags flags)
2706e732ea63SMichael S. Tsirkin {
2707836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2708836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2709836e1b38SFelipe Franciosi 
2710836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2711836e1b38SFelipe Franciosi         getter = property_get_uint32_ptr;
2712836e1b38SFelipe Franciosi     }
2713836e1b38SFelipe Franciosi 
2714836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2715836e1b38SFelipe Franciosi         setter = property_set_uint32_ptr;
2716836e1b38SFelipe Franciosi     }
2717836e1b38SFelipe Franciosi 
271870251887SMarkus Armbruster     return object_property_add(obj, name, "uint32",
2719d2623129SMarkus Armbruster                                getter, setter, NULL, (void *)v);
2720e732ea63SMichael S. Tsirkin }
2721e732ea63SMichael S. Tsirkin 
2722a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint32_ptr(ObjectClass * klass,const char * name,const uint32_t * v,ObjectPropertyFlags flags)2723a3a16211SMarc-André Lureau object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2724836e1b38SFelipe Franciosi                                      const uint32_t *v,
2725d2623129SMarkus Armbruster                                      ObjectPropertyFlags flags)
272616bf7f52SDaniel P. Berrange {
2727836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2728836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2729836e1b38SFelipe Franciosi 
2730836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2731836e1b38SFelipe Franciosi         getter = property_get_uint32_ptr;
2732836e1b38SFelipe Franciosi     }
2733836e1b38SFelipe Franciosi 
2734836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2735836e1b38SFelipe Franciosi         setter = property_set_uint32_ptr;
2736836e1b38SFelipe Franciosi     }
2737836e1b38SFelipe Franciosi 
2738a3a16211SMarc-André Lureau     return object_class_property_add(klass, name, "uint32",
2739d2623129SMarkus Armbruster                                      getter, setter, NULL, (void *)v);
274016bf7f52SDaniel P. Berrange }
274116bf7f52SDaniel P. Berrange 
274270251887SMarkus Armbruster ObjectProperty *
object_property_add_uint64_ptr(Object * obj,const char * name,const uint64_t * v,ObjectPropertyFlags flags)274370251887SMarkus Armbruster object_property_add_uint64_ptr(Object *obj, const char *name,
2744836e1b38SFelipe Franciosi                                const uint64_t *v,
2745d2623129SMarkus Armbruster                                ObjectPropertyFlags flags)
2746e732ea63SMichael S. Tsirkin {
2747836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2748836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2749836e1b38SFelipe Franciosi 
2750836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2751836e1b38SFelipe Franciosi         getter = property_get_uint64_ptr;
2752836e1b38SFelipe Franciosi     }
2753836e1b38SFelipe Franciosi 
2754836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2755836e1b38SFelipe Franciosi         setter = property_set_uint64_ptr;
2756836e1b38SFelipe Franciosi     }
2757836e1b38SFelipe Franciosi 
275870251887SMarkus Armbruster     return object_property_add(obj, name, "uint64",
2759d2623129SMarkus Armbruster                                getter, setter, NULL, (void *)v);
2760e732ea63SMichael S. Tsirkin }
2761e732ea63SMichael S. Tsirkin 
2762a3a16211SMarc-André Lureau ObjectProperty *
object_class_property_add_uint64_ptr(ObjectClass * klass,const char * name,const uint64_t * v,ObjectPropertyFlags flags)2763a3a16211SMarc-André Lureau object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2764836e1b38SFelipe Franciosi                                      const uint64_t *v,
2765d2623129SMarkus Armbruster                                      ObjectPropertyFlags flags)
276616bf7f52SDaniel P. Berrange {
2767836e1b38SFelipe Franciosi     ObjectPropertyAccessor *getter = NULL;
2768836e1b38SFelipe Franciosi     ObjectPropertyAccessor *setter = NULL;
2769836e1b38SFelipe Franciosi 
2770836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2771836e1b38SFelipe Franciosi         getter = property_get_uint64_ptr;
2772836e1b38SFelipe Franciosi     }
2773836e1b38SFelipe Franciosi 
2774836e1b38SFelipe Franciosi     if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2775836e1b38SFelipe Franciosi         setter = property_set_uint64_ptr;
2776836e1b38SFelipe Franciosi     }
2777836e1b38SFelipe Franciosi 
2778a3a16211SMarc-André Lureau     return object_class_property_add(klass, name, "uint64",
2779d2623129SMarkus Armbruster                                      getter, setter, NULL, (void *)v);
278016bf7f52SDaniel P. Berrange }
278116bf7f52SDaniel P. Berrange 
2782ef7c7ff6SStefan Hajnoczi typedef struct {
2783ef7c7ff6SStefan Hajnoczi     Object *target_obj;
27841590d266SEduardo Habkost     char *target_name;
2785ef7c7ff6SStefan Hajnoczi } AliasProperty;
2786ef7c7ff6SStefan Hajnoczi 
property_get_alias(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2787d7bce999SEric Blake static void property_get_alias(Object *obj, Visitor *v, const char *name,
2788d7bce999SEric Blake                                void *opaque, Error **errp)
2789ef7c7ff6SStefan Hajnoczi {
2790ef7c7ff6SStefan Hajnoczi     AliasProperty *prop = opaque;
2791cbc94d97SPaolo Bonzini     Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2792ef7c7ff6SStefan Hajnoczi 
2793cbc94d97SPaolo Bonzini     object_property_get(prop->target_obj, prop->target_name, alias_v, errp);
2794cbc94d97SPaolo Bonzini     visit_free(alias_v);
2795ef7c7ff6SStefan Hajnoczi }
2796ef7c7ff6SStefan Hajnoczi 
property_set_alias(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2797d7bce999SEric Blake static void property_set_alias(Object *obj, Visitor *v, const char *name,
2798d7bce999SEric Blake                                void *opaque, Error **errp)
2799ef7c7ff6SStefan Hajnoczi {
2800ef7c7ff6SStefan Hajnoczi     AliasProperty *prop = opaque;
2801cbc94d97SPaolo Bonzini     Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2802ef7c7ff6SStefan Hajnoczi 
2803cbc94d97SPaolo Bonzini     object_property_set(prop->target_obj, prop->target_name, alias_v, errp);
2804cbc94d97SPaolo Bonzini     visit_free(alias_v);
2805ef7c7ff6SStefan Hajnoczi }
2806ef7c7ff6SStefan Hajnoczi 
property_resolve_alias(Object * obj,void * opaque,const char * part)280764607d08SPaolo Bonzini static Object *property_resolve_alias(Object *obj, void *opaque,
2808ddfb0baaSMarkus Armbruster                                       const char *part)
280964607d08SPaolo Bonzini {
281064607d08SPaolo Bonzini     AliasProperty *prop = opaque;
281164607d08SPaolo Bonzini 
281264607d08SPaolo Bonzini     return object_resolve_path_component(prop->target_obj, prop->target_name);
281364607d08SPaolo Bonzini }
281464607d08SPaolo Bonzini 
property_release_alias(Object * obj,const char * name,void * opaque)2815ef7c7ff6SStefan Hajnoczi static void property_release_alias(Object *obj, const char *name, void *opaque)
2816ef7c7ff6SStefan Hajnoczi {
2817ef7c7ff6SStefan Hajnoczi     AliasProperty *prop = opaque;
2818ef7c7ff6SStefan Hajnoczi 
28191590d266SEduardo Habkost     g_free(prop->target_name);
2820ef7c7ff6SStefan Hajnoczi     g_free(prop);
2821ef7c7ff6SStefan Hajnoczi }
2822ef7c7ff6SStefan Hajnoczi 
282370251887SMarkus Armbruster ObjectProperty *
object_property_add_alias(Object * obj,const char * name,Object * target_obj,const char * target_name)282470251887SMarkus Armbruster object_property_add_alias(Object *obj, const char *name,
2825d2623129SMarkus Armbruster                           Object *target_obj, const char *target_name)
2826ef7c7ff6SStefan Hajnoczi {
2827ef7c7ff6SStefan Hajnoczi     AliasProperty *prop;
282864607d08SPaolo Bonzini     ObjectProperty *op;
2829ef7c7ff6SStefan Hajnoczi     ObjectProperty *target_prop;
283070251887SMarkus Armbruster     g_autofree char *prop_type = NULL;
2831ef7c7ff6SStefan Hajnoczi 
2832efba1595SDaniel P. Berrangé     target_prop = object_property_find_err(target_obj, target_name,
2833d2623129SMarkus Armbruster                                            &error_abort);
2834ef7c7ff6SStefan Hajnoczi 
2835d190698eSPaolo Bonzini     if (object_property_is_child(target_prop)) {
2836d190698eSPaolo Bonzini         prop_type = g_strdup_printf("link%s",
2837d190698eSPaolo Bonzini                                     target_prop->type + strlen("child"));
2838d190698eSPaolo Bonzini     } else {
2839d190698eSPaolo Bonzini         prop_type = g_strdup(target_prop->type);
2840d190698eSPaolo Bonzini     }
2841d190698eSPaolo Bonzini 
2842ef7c7ff6SStefan Hajnoczi     prop = g_malloc(sizeof(*prop));
2843ef7c7ff6SStefan Hajnoczi     prop->target_obj = target_obj;
28441590d266SEduardo Habkost     prop->target_name = g_strdup(target_name);
2845ef7c7ff6SStefan Hajnoczi 
2846d190698eSPaolo Bonzini     op = object_property_add(obj, name, prop_type,
2847ef7c7ff6SStefan Hajnoczi                              property_get_alias,
2848ef7c7ff6SStefan Hajnoczi                              property_set_alias,
2849ef7c7ff6SStefan Hajnoczi                              property_release_alias,
2850d2623129SMarkus Armbruster                              prop);
285164607d08SPaolo Bonzini     op->resolve = property_resolve_alias;
28520e76ed0aSMarc-André Lureau     if (target_prop->defval) {
28530e76ed0aSMarc-André Lureau         op->defval = qobject_ref(target_prop->defval);
28540e76ed0aSMarc-André Lureau     }
2855d190698eSPaolo Bonzini 
2856a18bb417SAndreas Färber     object_property_set_description(obj, op->name,
28577eecec7dSMarkus Armbruster                                     target_prop->description);
285870251887SMarkus Armbruster     return op;
2859ef7c7ff6SStefan Hajnoczi }
2860ef7c7ff6SStefan Hajnoczi 
object_property_set_description(Object * obj,const char * name,const char * description)286180742642SGonglei void object_property_set_description(Object *obj, const char *name,
28627eecec7dSMarkus Armbruster                                      const char *description)
286380742642SGonglei {
286480742642SGonglei     ObjectProperty *op;
286580742642SGonglei 
2866efba1595SDaniel P. Berrangé     op = object_property_find_err(obj, name, &error_abort);
286780742642SGonglei     g_free(op->description);
286880742642SGonglei     op->description = g_strdup(description);
286980742642SGonglei }
287080742642SGonglei 
object_class_property_set_description(ObjectClass * klass,const char * name,const char * description)287116bf7f52SDaniel P. Berrange void object_class_property_set_description(ObjectClass *klass,
287216bf7f52SDaniel P. Berrange                                            const char *name,
28737eecec7dSMarkus Armbruster                                            const char *description)
287416bf7f52SDaniel P. Berrange {
287516bf7f52SDaniel P. Berrange     ObjectProperty *op;
287616bf7f52SDaniel P. Berrange 
287716bf7f52SDaniel P. Berrange     op = g_hash_table_lookup(klass->properties, name);
287816bf7f52SDaniel P. Berrange     g_free(op->description);
287916bf7f52SDaniel P. Berrange     op->description = g_strdup(description);
288016bf7f52SDaniel P. Berrange }
288116bf7f52SDaniel P. Berrange 
object_class_init(ObjectClass * klass,void * data)28827439a036SMarc-André Lureau static void object_class_init(ObjectClass *klass, void *data)
28832f262e06SPaolo Bonzini {
288490c69fb9SMarkus Armbruster     object_class_property_add_str(klass, "type", object_get_type,
2885d2623129SMarkus Armbruster                                   NULL);
28862f262e06SPaolo Bonzini }
28872f262e06SPaolo Bonzini 
register_types(void)2888745549c8SPaolo Bonzini static void register_types(void)
2889745549c8SPaolo Bonzini {
28905e78c98bSBernhard Beschow     static const TypeInfo interface_info = {
2891745549c8SPaolo Bonzini         .name = TYPE_INTERFACE,
289233e95c63SAnthony Liguori         .class_size = sizeof(InterfaceClass),
2893745549c8SPaolo Bonzini         .abstract = true,
2894745549c8SPaolo Bonzini     };
2895745549c8SPaolo Bonzini 
28965e78c98bSBernhard Beschow     static const TypeInfo object_info = {
2897745549c8SPaolo Bonzini         .name = TYPE_OBJECT,
2898745549c8SPaolo Bonzini         .instance_size = sizeof(Object),
28997439a036SMarc-André Lureau         .class_init = object_class_init,
2900745549c8SPaolo Bonzini         .abstract = true,
2901745549c8SPaolo Bonzini     };
2902745549c8SPaolo Bonzini 
2903049cb3cfSPaolo Bonzini     type_interface = type_register_internal(&interface_info);
2904049cb3cfSPaolo Bonzini     type_register_internal(&object_info);
2905745549c8SPaolo Bonzini }
2906745549c8SPaolo Bonzini 
2907745549c8SPaolo Bonzini type_init(register_types)
2908