blob: dcb686348b07c0f4ba3c9b19b137e8b25d5ba5e7 [file] [log] [blame]
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001/*
2 * QEMU Object Model
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
Peter Maydell9bbc8532016-01-29 17:50:02 +000013#include "qemu/osdep.h"
Markus Armbruster13d4ff02019-08-12 07:23:37 +020014#include "hw/qdev-core.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010015#include "qapi/error.h"
Paolo Bonzini14cccb62012-12-17 18:19:50 +010016#include "qom/object.h"
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +010017#include "qom/object_interfaces.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020018#include "qemu/cutils.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010019#include "qapi/visitor.h"
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +010020#include "qapi/string-input-visitor.h"
21#include "qapi/string-output-visitor.h"
Markus Armbrustereb815e22018-02-11 10:36:05 +010022#include "qapi/qapi-builtin-visit.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010023#include "qapi/qmp/qerror.h"
Paolo Bonzinifa131d92013-05-10 14:16:39 +020024#include "trace.h"
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060025
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +010026/* TODO: replace QObject with a simpler visitor to avoid a dependency
27 * of the QOM core on QObject? */
Paolo Bonzini14cccb62012-12-17 18:19:50 +010028#include "qom/qom-qobject.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010029#include "qapi/qmp/qbool.h"
Markus Armbruster15280c32018-02-01 12:18:36 +010030#include "qapi/qmp/qnum.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010031#include "qapi/qmp/qstring.h"
Philippe Mathieu-Daudée02bdf12019-04-27 15:56:42 +020032#include "qemu/error-report.h"
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +010033
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060034#define MAX_INTERFACES 32
35
36typedef struct InterfaceImpl InterfaceImpl;
37typedef struct TypeImpl TypeImpl;
38
39struct InterfaceImpl
40{
Anthony Liguori33e95c62012-08-10 13:16:10 +100041 const char *typename;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060042};
43
44struct TypeImpl
45{
46 const char *name;
47
48 size_t class_size;
49
50 size_t instance_size;
51
52 void (*class_init)(ObjectClass *klass, void *data);
Paolo Bonzini3b50e312012-05-02 13:30:55 +020053 void (*class_base_init)(ObjectClass *klass, void *data);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060054
55 void *class_data;
56
57 void (*instance_init)(Object *obj);
Eduardo Habkost8231c2d2013-07-10 17:08:41 -030058 void (*instance_post_init)(Object *obj);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060059 void (*instance_finalize)(Object *obj);
60
61 bool abstract;
62
63 const char *parent;
64 TypeImpl *parent_type;
65
66 ObjectClass *class;
67
68 int num_interfaces;
69 InterfaceImpl interfaces[MAX_INTERFACES];
70};
71
Paolo Bonzini9970bd82012-02-03 11:51:39 +010072static Type type_interface;
73
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060074static GHashTable *type_table_get(void)
75{
76 static GHashTable *type_table;
77
78 if (type_table == NULL) {
79 type_table = g_hash_table_new(g_str_hash, g_str_equal);
80 }
81
82 return type_table;
83}
84
Hervé Poussineauf54c19c2013-12-03 16:42:00 +010085static bool enumerating_types;
86
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060087static void type_table_add(TypeImpl *ti)
88{
Hervé Poussineauf54c19c2013-12-03 16:42:00 +010089 assert(!enumerating_types);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060090 g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
91}
92
93static TypeImpl *type_table_lookup(const char *name)
94{
95 return g_hash_table_lookup(type_table_get(), name);
96}
97
Paolo Bonzinib061dc42013-12-03 16:41:59 +010098static TypeImpl *type_new(const TypeInfo *info)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060099{
100 TypeImpl *ti = g_malloc0(sizeof(*ti));
Anthony Liguori33e95c62012-08-10 13:16:10 +1000101 int i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600102
103 g_assert(info->name != NULL);
104
Anthony Liguori73093352012-01-25 13:37:36 -0600105 if (type_table_lookup(info->name) != NULL) {
106 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
107 abort();
108 }
109
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600110 ti->name = g_strdup(info->name);
111 ti->parent = g_strdup(info->parent);
112
113 ti->class_size = info->class_size;
114 ti->instance_size = info->instance_size;
115
116 ti->class_init = info->class_init;
Paolo Bonzini3b50e312012-05-02 13:30:55 +0200117 ti->class_base_init = info->class_base_init;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600118 ti->class_data = info->class_data;
119
120 ti->instance_init = info->instance_init;
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300121 ti->instance_post_init = info->instance_post_init;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600122 ti->instance_finalize = info->instance_finalize;
123
124 ti->abstract = info->abstract;
125
Anthony Liguori33e95c62012-08-10 13:16:10 +1000126 for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
127 ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600128 }
Anthony Liguori33e95c62012-08-10 13:16:10 +1000129 ti->num_interfaces = i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600130
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100131 return ti;
132}
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600133
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100134static TypeImpl *type_register_internal(const TypeInfo *info)
135{
136 TypeImpl *ti;
137 ti = type_new(info);
138
139 type_table_add(ti);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600140 return ti;
141}
142
Paolo Bonzini049cb3c2012-04-04 15:58:40 +0200143TypeImpl *type_register(const TypeInfo *info)
144{
145 assert(info->parent);
146 return type_register_internal(info);
147}
148
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600149TypeImpl *type_register_static(const TypeInfo *info)
150{
151 return type_register(info);
152}
153
Igor Mammedovaa04c9d22017-10-09 21:50:49 +0200154void type_register_static_array(const TypeInfo *infos, int nr_infos)
155{
156 int i;
157
158 for (i = 0; i < nr_infos; i++) {
159 type_register_static(&infos[i]);
160 }
161}
162
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600163static TypeImpl *type_get_by_name(const char *name)
164{
165 if (name == NULL) {
166 return NULL;
167 }
168
169 return type_table_lookup(name);
170}
171
172static TypeImpl *type_get_parent(TypeImpl *type)
173{
174 if (!type->parent_type && type->parent) {
175 type->parent_type = type_get_by_name(type->parent);
Philippe Mathieu-Daudé89d337f2020-01-21 12:03:45 +0100176 if (!type->parent_type) {
177 fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
178 type->name, type->parent);
179 abort();
180 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600181 }
182
183 return type->parent_type;
184}
185
186static bool type_has_parent(TypeImpl *type)
187{
188 return (type->parent != NULL);
189}
190
191static size_t type_class_get_size(TypeImpl *ti)
192{
193 if (ti->class_size) {
194 return ti->class_size;
195 }
196
197 if (type_has_parent(ti)) {
198 return type_class_get_size(type_get_parent(ti));
199 }
200
201 return sizeof(ObjectClass);
202}
203
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400204static size_t type_object_get_size(TypeImpl *ti)
205{
206 if (ti->instance_size) {
207 return ti->instance_size;
208 }
209
210 if (type_has_parent(ti)) {
211 return type_object_get_size(type_get_parent(ti));
212 }
213
214 return 0;
215}
216
Bharata B Rao3f97b532016-06-10 06:29:00 +0530217size_t object_type_get_instance_size(const char *typename)
218{
219 TypeImpl *type = type_get_by_name(typename);
220
221 g_assert(type != NULL);
222 return type_object_get_size(type);
223}
224
Anthony Liguori33e95c62012-08-10 13:16:10 +1000225static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600226{
Anthony Liguori33e95c62012-08-10 13:16:10 +1000227 assert(target_type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600228
Cao jinb30d8052015-11-03 10:36:42 +0800229 /* Check if target_type is a direct ancestor of type */
Anthony Liguori33e95c62012-08-10 13:16:10 +1000230 while (type) {
231 if (type == target_type) {
232 return true;
233 }
234
235 type = type_get_parent(type);
236 }
237
238 return false;
239}
240
241static void type_initialize(TypeImpl *ti);
242
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100243static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
244 TypeImpl *parent_type)
Anthony Liguori33e95c62012-08-10 13:16:10 +1000245{
246 InterfaceClass *new_iface;
247 TypeInfo info = { };
248 TypeImpl *iface_impl;
249
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100250 info.parent = parent_type->name;
251 info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000252 info.abstract = true;
253
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100254 iface_impl = type_new(&info);
255 iface_impl->parent_type = parent_type;
Anthony Liguori33e95c62012-08-10 13:16:10 +1000256 type_initialize(iface_impl);
257 g_free((char *)info.name);
258
259 new_iface = (InterfaceClass *)iface_impl->class;
260 new_iface->concrete_class = ti->class;
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100261 new_iface->interface_type = interface_type;
Anthony Liguori33e95c62012-08-10 13:16:10 +1000262
263 ti->class->interfaces = g_slist_append(ti->class->interfaces,
264 iface_impl->class);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600265}
266
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100267static void object_property_free(gpointer data)
268{
269 ObjectProperty *prop = data;
270
271 g_free(prop->name);
272 g_free(prop->type);
273 g_free(prop->description);
274 g_free(prop);
275}
276
Igor Mitsyankoac451032012-02-28 15:57:11 +0400277static void type_initialize(TypeImpl *ti)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600278{
Paolo Bonzini745549c2012-03-31 16:45:54 +0200279 TypeImpl *parent;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600280
281 if (ti->class) {
282 return;
283 }
284
285 ti->class_size = type_class_get_size(ti);
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400286 ti->instance_size = type_object_get_size(ti);
Eduardo Habkost1c6d75d2016-12-12 16:31:01 -0200287 /* Any type with zero instance_size is implicitly abstract.
288 * This means interface types are all abstract.
289 */
290 if (ti->instance_size == 0) {
291 ti->abstract = true;
292 }
Marc-André Lureau422ca142018-09-12 16:53:03 +0400293 if (type_is_ancestor(ti, type_interface)) {
294 assert(ti->instance_size == 0);
295 assert(ti->abstract);
296 assert(!ti->instance_init);
297 assert(!ti->instance_post_init);
298 assert(!ti->instance_finalize);
299 assert(!ti->num_interfaces);
300 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600301 ti->class = g_malloc0(ti->class_size);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600302
Paolo Bonzini745549c2012-03-31 16:45:54 +0200303 parent = type_get_parent(ti);
304 if (parent) {
Igor Mitsyankoac451032012-02-28 15:57:11 +0400305 type_initialize(parent);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000306 GSList *e;
307 int i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600308
Markus Armbruster719a3072018-06-08 19:02:31 +0200309 g_assert(parent->class_size <= ti->class_size);
Marc-André Lureaud5e633f2020-01-10 19:30:14 +0400310 g_assert(parent->instance_size <= ti->instance_size);
Paolo Bonzini745549c2012-03-31 16:45:54 +0200311 memcpy(ti->class, parent->class, parent->class_size);
Peter Crosthwaite3e407de2013-02-19 14:02:09 +1000312 ti->class->interfaces = NULL;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100313 ti->class->properties = g_hash_table_new_full(
314 g_str_hash, g_str_equal, g_free, object_property_free);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000315
316 for (e = parent->class->interfaces; e; e = e->next) {
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100317 InterfaceClass *iface = e->data;
318 ObjectClass *klass = OBJECT_CLASS(iface);
319
320 type_initialize_interface(ti, iface->interface_type, klass->type);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000321 }
322
323 for (i = 0; i < ti->num_interfaces; i++) {
324 TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
Philippe Mathieu-Daudéa9ee3a92020-01-18 17:23:48 +0100325 if (!t) {
326 error_report("missing interface '%s' for object '%s'",
327 ti->interfaces[i].typename, parent->name);
328 abort();
329 }
Anthony Liguori33e95c62012-08-10 13:16:10 +1000330 for (e = ti->class->interfaces; e; e = e->next) {
331 TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
332
333 if (type_is_ancestor(target_type, t)) {
334 break;
335 }
336 }
337
338 if (e) {
339 continue;
340 }
341
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100342 type_initialize_interface(ti, t, t);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000343 }
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100344 } else {
345 ti->class->properties = g_hash_table_new_full(
346 g_str_hash, g_str_equal, g_free, object_property_free);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600347 }
348
Paolo Bonzini745549c2012-03-31 16:45:54 +0200349 ti->class->type = ti;
350
351 while (parent) {
352 if (parent->class_base_init) {
353 parent->class_base_init(ti->class, ti->class_data);
354 }
355 parent = type_get_parent(parent);
356 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600357
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600358 if (ti->class_init) {
359 ti->class_init(ti->class, ti->class_data);
360 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600361}
362
363static void object_init_with_type(Object *obj, TypeImpl *ti)
364{
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600365 if (type_has_parent(ti)) {
366 object_init_with_type(obj, type_get_parent(ti));
367 }
368
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600369 if (ti->instance_init) {
370 ti->instance_init(obj);
371 }
372}
373
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300374static void object_post_init_with_type(Object *obj, TypeImpl *ti)
375{
376 if (ti->instance_post_init) {
377 ti->instance_post_init(obj);
378 }
379
380 if (type_has_parent(ti)) {
381 object_post_init_with_type(obj, type_get_parent(ti));
382 }
383}
384
Marc-André Lureauea9ce892018-11-26 22:04:32 +0400385void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp)
386{
Marc-André Lureauea9ce892018-11-26 22:04:32 +0400387 int i;
388
389 if (!props) {
390 return;
391 }
392
393 for (i = 0; i < props->len; i++) {
394 GlobalProperty *p = g_ptr_array_index(props, i);
Eduardo Habkostd769f0d2019-01-10 00:02:57 -0200395 Error *err = NULL;
Marc-André Lureauea9ce892018-11-26 22:04:32 +0400396
397 if (object_dynamic_cast(obj, p->driver) == NULL) {
398 continue;
399 }
Dr. David Alan Gilbert92fd4532019-07-29 17:29:02 +0100400 if (p->optional && !object_property_find(obj, p->property, NULL)) {
401 continue;
402 }
Marc-André Lureauea9ce892018-11-26 22:04:32 +0400403 p->used = true;
404 object_property_parse(obj, p->value, p->property, &err);
405 if (err != NULL) {
406 error_prepend(&err, "can't apply global %s.%s=%s: ",
407 p->driver, p->property, p->value);
Marc-André Lureau50545b22018-11-07 15:35:34 +0400408 /*
409 * If errp != NULL, propagate error and return.
410 * If errp == NULL, report a warning, but keep going
411 * with the remaining globals.
412 */
413 if (errp) {
414 error_propagate(errp, err);
415 return;
416 } else {
417 warn_report_err(err);
418 }
Marc-André Lureauea9ce892018-11-26 22:04:32 +0400419 }
420 }
421}
422
Markus Armbruster617902a2019-03-08 14:14:35 +0100423/*
424 * Global property defaults
425 * Slot 0: accelerator's global property defaults
426 * Slot 1: machine's global property defaults
Paolo Bonzini1fff3c22019-11-13 13:33:44 +0100427 * Slot 2: global properties from legacy command line option
Markus Armbruster617902a2019-03-08 14:14:35 +0100428 * Each is a GPtrArray of of GlobalProperty.
429 * Applied in order, later entries override earlier ones.
430 */
Paolo Bonzini1fff3c22019-11-13 13:33:44 +0100431static GPtrArray *object_compat_props[3];
432
433/*
434 * Retrieve @GPtrArray for global property defined with options
435 * other than "-global". These are generally used for syntactic
436 * sugar and legacy command line options.
437 */
438void object_register_sugar_prop(const char *driver, const char *prop, const char *value)
439{
440 GlobalProperty *g;
441 if (!object_compat_props[2]) {
442 object_compat_props[2] = g_ptr_array_new();
443 }
444 g = g_new0(GlobalProperty, 1);
445 g->driver = g_strdup(driver);
446 g->property = g_strdup(prop);
447 g->value = g_strdup(value);
448 g_ptr_array_add(object_compat_props[2], g);
449}
Markus Armbruster617902a2019-03-08 14:14:35 +0100450
451/*
452 * Set machine's global property defaults to @compat_props.
453 * May be called at most once.
454 */
455void object_set_machine_compat_props(GPtrArray *compat_props)
456{
457 assert(!object_compat_props[1]);
458 object_compat_props[1] = compat_props;
459}
460
461/*
462 * Set accelerator's global property defaults to @compat_props.
463 * May be called at most once.
464 */
465void object_set_accelerator_compat_props(GPtrArray *compat_props)
466{
467 assert(!object_compat_props[0]);
468 object_compat_props[0] = compat_props;
469}
470
471void object_apply_compat_props(Object *obj)
472{
473 int i;
474
475 for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
476 object_apply_global_props(obj, object_compat_props[i],
Paolo Bonzini1fff3c22019-11-13 13:33:44 +0100477 i == 2 ? &error_fatal : &error_abort);
Markus Armbruster617902a2019-03-08 14:14:35 +0100478 }
479}
480
Marc-André Lureau63f7b102016-12-12 20:31:51 +0300481static void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600482{
483 Object *obj = data;
484
Igor Mitsyankoac451032012-02-28 15:57:11 +0400485 type_initialize(type);
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400486
Markus Armbruster719a3072018-06-08 19:02:31 +0200487 g_assert(type->instance_size >= sizeof(Object));
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600488 g_assert(type->abstract == false);
Markus Armbruster719a3072018-06-08 19:02:31 +0200489 g_assert(size >= type->instance_size);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600490
491 memset(obj, 0, type->instance_size);
492 obj->class = type->class;
Paolo Bonzini764b6312012-11-23 09:47:12 +0100493 object_ref(obj);
Pavel Fedinb604a852015-10-13 13:37:45 +0100494 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
495 NULL, object_property_free);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600496 object_init_with_type(obj, type);
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300497 object_post_init_with_type(obj, type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600498}
499
Andreas Färber213f0c42013-08-23 19:37:12 +0200500void object_initialize(void *data, size_t size, const char *typename)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600501{
502 TypeImpl *type = type_get_by_name(typename);
503
Philippe Mathieu-Daudée02bdf12019-04-27 15:56:42 +0200504 if (!type) {
505 error_report("missing object type '%s'", typename);
506 abort();
507 }
508
Andreas Färber5b9237f2013-08-30 18:28:37 +0200509 object_initialize_with_type(data, size, type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600510}
511
Thomas Huth0210b392018-07-16 14:59:18 +0200512void object_initialize_child(Object *parentobj, const char *propname,
513 void *childobj, size_t size, const char *type,
514 Error **errp, ...)
515{
516 va_list vargs;
517
518 va_start(vargs, errp);
519 object_initialize_childv(parentobj, propname, childobj, size, type, errp,
520 vargs);
521 va_end(vargs);
522}
523
524void object_initialize_childv(Object *parentobj, const char *propname,
525 void *childobj, size_t size, const char *type,
526 Error **errp, va_list vargs)
527{
528 Error *local_err = NULL;
529 Object *obj;
Marc-André Lureau3650b2d2018-12-04 18:20:07 +0400530 UserCreatable *uc;
Thomas Huth0210b392018-07-16 14:59:18 +0200531
532 object_initialize(childobj, size, type);
533 obj = OBJECT(childobj);
534
535 object_set_propv(obj, &local_err, vargs);
536 if (local_err) {
537 goto out;
538 }
539
540 object_property_add_child(parentobj, propname, obj, &local_err);
541 if (local_err) {
542 goto out;
543 }
544
Marc-André Lureau3650b2d2018-12-04 18:20:07 +0400545 uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
546 if (uc) {
547 user_creatable_complete(uc, &local_err);
Thomas Huth0210b392018-07-16 14:59:18 +0200548 if (local_err) {
549 object_unparent(obj);
550 goto out;
551 }
552 }
553
554 /*
555 * Since object_property_add_child added a reference to the child object,
556 * we can drop the reference added by object_initialize(), so the child
557 * property will own the only reference to the object.
558 */
559 object_unref(obj);
560
561out:
562 if (local_err) {
563 error_propagate(errp, local_err);
564 object_unref(obj);
565 }
566}
567
Andreas Färber5d9d3f42012-05-27 00:32:40 +0200568static inline bool object_property_is_child(ObjectProperty *prop)
569{
570 return strstart(prop->type, "child<", NULL);
571}
572
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600573static void object_property_del_all(Object *obj)
574{
Pavel Fedinb604a852015-10-13 13:37:45 +0100575 ObjectProperty *prop;
576 GHashTableIter iter;
577 gpointer key, value;
578 bool released;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600579
Pavel Fedinb604a852015-10-13 13:37:45 +0100580 do {
581 released = false;
582 g_hash_table_iter_init(&iter, obj->properties);
583 while (g_hash_table_iter_next(&iter, &key, &value)) {
584 prop = value;
585 if (prop->release) {
586 prop->release(obj, prop->name, prop->opaque);
587 prop->release = NULL;
588 released = true;
589 break;
590 }
591 g_hash_table_iter_remove(&iter);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600592 }
Pavel Fedinb604a852015-10-13 13:37:45 +0100593 } while (released);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600594
Pavel Fedinb604a852015-10-13 13:37:45 +0100595 g_hash_table_unref(obj->properties);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600596}
597
598static void object_property_del_child(Object *obj, Object *child, Error **errp)
599{
600 ObjectProperty *prop;
Pavel Fedinb604a852015-10-13 13:37:45 +0100601 GHashTableIter iter;
602 gpointer key, value;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600603
Pavel Fedinb604a852015-10-13 13:37:45 +0100604 g_hash_table_iter_init(&iter, obj->properties);
605 while (g_hash_table_iter_next(&iter, &key, &value)) {
606 prop = value;
Andreas Färber5d9d3f42012-05-27 00:32:40 +0200607 if (object_property_is_child(prop) && prop->opaque == child) {
Pavel Fedinb604a852015-10-13 13:37:45 +0100608 if (prop->release) {
609 prop->release(obj, prop->name, prop->opaque);
610 prop->release = NULL;
611 }
612 break;
613 }
614 }
615 g_hash_table_iter_init(&iter, obj->properties);
616 while (g_hash_table_iter_next(&iter, &key, &value)) {
617 prop = value;
618 if (object_property_is_child(prop) && prop->opaque == child) {
619 g_hash_table_iter_remove(&iter);
Paolo Bonzini6c1fdcf2012-02-28 09:54:15 +0100620 break;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600621 }
622 }
623}
624
625void object_unparent(Object *obj)
626{
Michael S. Tsirkine998fa82013-03-18 21:01:37 +0200627 if (obj->parent) {
628 object_property_del_child(obj->parent, obj, NULL);
629 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600630}
631
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600632static void object_deinit(Object *obj, TypeImpl *type)
633{
634 if (type->instance_finalize) {
635 type->instance_finalize(obj);
636 }
637
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600638 if (type_has_parent(type)) {
639 object_deinit(obj, type_get_parent(type));
640 }
641}
642
Paolo Bonzini339c2702012-11-23 09:47:16 +0100643static void object_finalize(void *data)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600644{
645 Object *obj = data;
646 TypeImpl *ti = obj->class->type;
647
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600648 object_property_del_all(obj);
Paolo Bonzini76a6e1c2014-06-11 11:58:30 +0200649 object_deinit(obj, ti);
Anthony Liguoridb85b572011-12-23 08:47:39 -0600650
Markus Armbruster719a3072018-06-08 19:02:31 +0200651 g_assert(obj->ref == 0);
Paolo Bonzinifde9bf42012-11-23 09:47:14 +0100652 if (obj->free) {
653 obj->free(obj);
654 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600655}
656
Marc-André Lureau63f7b102016-12-12 20:31:51 +0300657static Object *object_new_with_type(Type type)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600658{
659 Object *obj;
660
661 g_assert(type != NULL);
Igor Mitsyankoac451032012-02-28 15:57:11 +0400662 type_initialize(type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600663
664 obj = g_malloc(type->instance_size);
Andreas Färber5b9237f2013-08-30 18:28:37 +0200665 object_initialize_with_type(obj, type->instance_size, type);
Paolo Bonzinifde9bf42012-11-23 09:47:14 +0100666 obj->free = g_free;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600667
668 return obj;
669}
670
Paolo Bonzini3c75e122019-11-13 13:57:55 +0100671Object *object_new_with_class(ObjectClass *klass)
672{
673 return object_new_with_type(klass->type);
674}
675
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600676Object *object_new(const char *typename)
677{
678 TypeImpl *ti = type_get_by_name(typename);
679
680 return object_new_with_type(ti);
681}
682
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100683
684Object *object_new_with_props(const char *typename,
685 Object *parent,
686 const char *id,
687 Error **errp,
688 ...)
689{
690 va_list vargs;
691 Object *obj;
692
693 va_start(vargs, errp);
694 obj = object_new_with_propv(typename, parent, id, errp, vargs);
695 va_end(vargs);
696
697 return obj;
698}
699
700
701Object *object_new_with_propv(const char *typename,
702 Object *parent,
703 const char *id,
704 Error **errp,
705 va_list vargs)
706{
707 Object *obj;
708 ObjectClass *klass;
709 Error *local_err = NULL;
Marc-André Lureau3650b2d2018-12-04 18:20:07 +0400710 UserCreatable *uc;
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100711
712 klass = object_class_by_name(typename);
713 if (!klass) {
714 error_setg(errp, "invalid object type: %s", typename);
715 return NULL;
716 }
717
718 if (object_class_is_abstract(klass)) {
719 error_setg(errp, "object type '%s' is abstract", typename);
720 return NULL;
721 }
Wei Yang66e11552019-03-11 16:32:34 +0800722 obj = object_new_with_type(klass->type);
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100723
724 if (object_set_propv(obj, &local_err, vargs) < 0) {
725 goto error;
726 }
727
Daniel P. Berrangé6134d752018-06-15 16:39:35 +0100728 if (id != NULL) {
729 object_property_add_child(parent, id, obj, &local_err);
730 if (local_err) {
731 goto error;
732 }
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100733 }
734
Marc-André Lureau3650b2d2018-12-04 18:20:07 +0400735 uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
736 if (uc) {
737 user_creatable_complete(uc, &local_err);
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100738 if (local_err) {
Daniel P. Berrangé6134d752018-06-15 16:39:35 +0100739 if (id != NULL) {
740 object_unparent(obj);
741 }
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100742 goto error;
743 }
744 }
745
746 object_unref(OBJECT(obj));
747 return obj;
748
749 error:
Eduardo Habkost621ff942016-06-13 18:57:56 -0300750 error_propagate(errp, local_err);
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100751 object_unref(obj);
752 return NULL;
753}
754
755
756int object_set_props(Object *obj,
757 Error **errp,
758 ...)
759{
760 va_list vargs;
761 int ret;
762
763 va_start(vargs, errp);
764 ret = object_set_propv(obj, errp, vargs);
765 va_end(vargs);
766
767 return ret;
768}
769
770
771int object_set_propv(Object *obj,
772 Error **errp,
773 va_list vargs)
774{
775 const char *propname;
776 Error *local_err = NULL;
777
778 propname = va_arg(vargs, char *);
779 while (propname != NULL) {
780 const char *value = va_arg(vargs, char *);
781
782 g_assert(value != NULL);
783 object_property_parse(obj, value, propname, &local_err);
784 if (local_err) {
785 error_propagate(errp, local_err);
786 return -1;
787 }
788 propname = va_arg(vargs, char *);
789 }
790
791 return 0;
792}
793
794
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600795Object *object_dynamic_cast(Object *obj, const char *typename)
796{
Paolo Bonzinib7f43fe2012-11-23 16:56:17 +0100797 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
Paolo Bonziniacc4af32012-02-03 11:57:23 +0100798 return obj;
799 }
800
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600801 return NULL;
802}
803
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200804Object *object_dynamic_cast_assert(Object *obj, const char *typename,
805 const char *file, int line, const char *func)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600806{
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200807 trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
808 typename, file, line, func);
809
Paolo Bonzini3556c232013-05-10 14:16:40 +0200810#ifdef CONFIG_QOM_CAST_DEBUG
Anthony Liguori03587322013-05-13 15:22:24 -0500811 int i;
812 Object *inst;
813
Peter Crosthwaite95916ab2013-05-22 11:19:16 +1000814 for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100815 if (atomic_read(&obj->class->object_cast_cache[i]) == typename) {
Anthony Liguori03587322013-05-13 15:22:24 -0500816 goto out;
817 }
818 }
819
820 inst = object_dynamic_cast(obj, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600821
Paolo Bonzinib7f43fe2012-11-23 16:56:17 +0100822 if (!inst && obj) {
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200823 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
824 file, line, func, obj, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600825 abort();
826 }
827
Paolo Bonzini3556c232013-05-10 14:16:40 +0200828 assert(obj == inst);
Anthony Liguori03587322013-05-13 15:22:24 -0500829
Peter Crosthwaite95916ab2013-05-22 11:19:16 +1000830 if (obj && obj == inst) {
Anthony Liguori03587322013-05-13 15:22:24 -0500831 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100832 atomic_set(&obj->class->object_cast_cache[i - 1],
833 atomic_read(&obj->class->object_cast_cache[i]));
Anthony Liguori03587322013-05-13 15:22:24 -0500834 }
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100835 atomic_set(&obj->class->object_cast_cache[i - 1], typename);
Anthony Liguori03587322013-05-13 15:22:24 -0500836 }
837
838out:
Paolo Bonzini3556c232013-05-10 14:16:40 +0200839#endif
840 return obj;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600841}
842
843ObjectClass *object_class_dynamic_cast(ObjectClass *class,
844 const char *typename)
845{
Anthony Liguori33e95c62012-08-10 13:16:10 +1000846 ObjectClass *ret = NULL;
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200847 TypeImpl *target_type;
848 TypeImpl *type;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600849
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200850 if (!class) {
851 return NULL;
852 }
853
Paolo Bonzini793c96b2013-05-10 14:16:37 +0200854 /* A simple fast path that can trigger a lot for leaf classes. */
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200855 type = class->type;
Paolo Bonzini793c96b2013-05-10 14:16:37 +0200856 if (type->name == typename) {
857 return class;
858 }
859
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200860 target_type = type_get_by_name(typename);
Alexander Graf9ab880b2013-04-30 15:02:16 +0200861 if (!target_type) {
862 /* target class type unknown, so fail the cast */
863 return NULL;
864 }
865
Peter Crosthwaite00e2cea2013-02-19 14:02:10 +1000866 if (type->class->interfaces &&
867 type_is_ancestor(target_type, type_interface)) {
Anthony Liguori33e95c62012-08-10 13:16:10 +1000868 int found = 0;
869 GSList *i;
870
871 for (i = class->interfaces; i; i = i->next) {
872 ObjectClass *target_class = i->data;
873
874 if (type_is_ancestor(target_class->type, target_type)) {
875 ret = target_class;
876 found++;
877 }
878 }
879
880 /* The match was ambiguous, don't allow a cast */
881 if (found > 1) {
882 ret = NULL;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600883 }
Anthony Liguori33e95c62012-08-10 13:16:10 +1000884 } else if (type_is_ancestor(type, target_type)) {
885 ret = class;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600886 }
887
Anthony Liguori33e95c62012-08-10 13:16:10 +1000888 return ret;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600889}
890
891ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200892 const char *typename,
893 const char *file, int line,
894 const char *func)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600895{
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200896 ObjectClass *ret;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600897
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200898 trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
899 typename, file, line, func);
900
Anthony Liguori03587322013-05-13 15:22:24 -0500901#ifdef CONFIG_QOM_CAST_DEBUG
902 int i;
903
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000904 for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100905 if (atomic_read(&class->class_cast_cache[i]) == typename) {
Anthony Liguori03587322013-05-13 15:22:24 -0500906 ret = class;
907 goto out;
908 }
909 }
910#else
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000911 if (!class || !class->interfaces) {
Paolo Bonzini3556c232013-05-10 14:16:40 +0200912 return class;
913 }
914#endif
915
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200916 ret = object_class_dynamic_cast(class, typename);
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200917 if (!ret && class) {
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200918 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
919 file, line, func, class, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600920 abort();
921 }
922
Anthony Liguori03587322013-05-13 15:22:24 -0500923#ifdef CONFIG_QOM_CAST_DEBUG
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000924 if (class && ret == class) {
Anthony Liguori03587322013-05-13 15:22:24 -0500925 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100926 atomic_set(&class->class_cast_cache[i - 1],
927 atomic_read(&class->class_cast_cache[i]));
Anthony Liguori03587322013-05-13 15:22:24 -0500928 }
Alex Bennéeb6b3ccf2016-09-30 22:30:57 +0100929 atomic_set(&class->class_cast_cache[i - 1], typename);
Anthony Liguori03587322013-05-13 15:22:24 -0500930 }
931out:
932#endif
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600933 return ret;
934}
935
Igor Mammedov8f5d58e2017-07-14 10:14:50 +0800936const char *object_get_typename(const Object *obj)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600937{
938 return obj->class->type->name;
939}
940
941ObjectClass *object_get_class(Object *obj)
942{
943 return obj->class;
944}
945
Andreas Färber17862372013-01-23 12:20:18 +0100946bool object_class_is_abstract(ObjectClass *klass)
947{
948 return klass->type->abstract;
949}
950
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600951const char *object_class_get_name(ObjectClass *klass)
952{
953 return klass->type->name;
954}
955
956ObjectClass *object_class_by_name(const char *typename)
957{
958 TypeImpl *type = type_get_by_name(typename);
959
960 if (!type) {
961 return NULL;
962 }
963
Igor Mitsyankoac451032012-02-28 15:57:11 +0400964 type_initialize(type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600965
966 return type->class;
967}
968
Paolo Bonzinie7cce672012-05-02 13:30:54 +0200969ObjectClass *object_class_get_parent(ObjectClass *class)
970{
971 TypeImpl *type = type_get_parent(class->type);
972
973 if (!type) {
974 return NULL;
975 }
976
977 type_initialize(type);
978
979 return type->class;
980}
981
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600982typedef struct OCFData
983{
984 void (*fn)(ObjectClass *klass, void *opaque);
Anthony Liguori93c511a2011-12-22 14:11:53 -0600985 const char *implements_type;
986 bool include_abstract;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600987 void *opaque;
988} OCFData;
989
990static void object_class_foreach_tramp(gpointer key, gpointer value,
991 gpointer opaque)
992{
993 OCFData *data = opaque;
994 TypeImpl *type = value;
Anthony Liguori93c511a2011-12-22 14:11:53 -0600995 ObjectClass *k;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600996
Igor Mitsyankoac451032012-02-28 15:57:11 +0400997 type_initialize(type);
Anthony Liguori93c511a2011-12-22 14:11:53 -0600998 k = type->class;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600999
Anthony Liguori93c511a2011-12-22 14:11:53 -06001000 if (!data->include_abstract && type->abstract) {
1001 return;
1002 }
1003
1004 if (data->implements_type &&
1005 !object_class_dynamic_cast(k, data->implements_type)) {
1006 return;
1007 }
1008
1009 data->fn(k, data->opaque);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001010}
1011
1012void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
Anthony Liguori93c511a2011-12-22 14:11:53 -06001013 const char *implements_type, bool include_abstract,
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001014 void *opaque)
1015{
Anthony Liguori93c511a2011-12-22 14:11:53 -06001016 OCFData data = { fn, implements_type, include_abstract, opaque };
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001017
Hervé Poussineauf54c19c2013-12-03 16:42:00 +01001018 enumerating_types = true;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001019 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
Hervé Poussineauf54c19c2013-12-03 16:42:00 +01001020 enumerating_types = false;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -06001021}
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001022
Peter Crosthwaited714b8d2015-09-08 17:38:43 +01001023static int do_object_child_foreach(Object *obj,
1024 int (*fn)(Object *child, void *opaque),
1025 void *opaque, bool recurse)
Paolo Bonzini32efc532012-04-11 23:30:20 +02001026{
Pavel Fedinb604a852015-10-13 13:37:45 +01001027 GHashTableIter iter;
1028 ObjectProperty *prop;
Paolo Bonzini32efc532012-04-11 23:30:20 +02001029 int ret = 0;
1030
Pavel Fedinb604a852015-10-13 13:37:45 +01001031 g_hash_table_iter_init(&iter, obj->properties);
1032 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Paolo Bonzini32efc532012-04-11 23:30:20 +02001033 if (object_property_is_child(prop)) {
Peter Crosthwaited714b8d2015-09-08 17:38:43 +01001034 Object *child = prop->opaque;
1035
1036 ret = fn(child, opaque);
Paolo Bonzini32efc532012-04-11 23:30:20 +02001037 if (ret != 0) {
1038 break;
1039 }
Peter Crosthwaited714b8d2015-09-08 17:38:43 +01001040 if (recurse) {
1041 do_object_child_foreach(child, fn, opaque, true);
1042 }
Paolo Bonzini32efc532012-04-11 23:30:20 +02001043 }
1044 }
1045 return ret;
1046}
1047
Peter Crosthwaited714b8d2015-09-08 17:38:43 +01001048int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
1049 void *opaque)
1050{
1051 return do_object_child_foreach(obj, fn, opaque, false);
1052}
1053
1054int object_child_foreach_recursive(Object *obj,
1055 int (*fn)(Object *child, void *opaque),
1056 void *opaque)
1057{
1058 return do_object_child_foreach(obj, fn, opaque, true);
1059}
1060
Andreas Färber418ba9e2012-02-25 23:07:34 +01001061static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
1062{
1063 GSList **list = opaque;
1064
1065 *list = g_slist_prepend(*list, klass);
1066}
1067
1068GSList *object_class_get_list(const char *implements_type,
1069 bool include_abstract)
1070{
1071 GSList *list = NULL;
1072
1073 object_class_foreach(object_class_get_list_tramp,
1074 implements_type, include_abstract, &list);
1075 return list;
1076}
1077
Paolo Bonzini47c66002018-03-03 08:33:10 +01001078static gint object_class_cmp(gconstpointer a, gconstpointer b)
1079{
1080 return strcasecmp(object_class_get_name((ObjectClass *)a),
1081 object_class_get_name((ObjectClass *)b));
1082}
1083
1084GSList *object_class_get_list_sorted(const char *implements_type,
1085 bool include_abstract)
1086{
1087 return g_slist_sort(object_class_get_list(implements_type, include_abstract),
1088 object_class_cmp);
1089}
1090
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001091void object_ref(Object *obj)
1092{
Peter Crosthwaite8ffad852014-06-05 23:13:36 -07001093 if (!obj) {
1094 return;
1095 }
Andreas Färber8438a132015-11-16 17:49:20 +01001096 atomic_inc(&obj->ref);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001097}
1098
1099void object_unref(Object *obj)
1100{
Peter Crosthwaite8ffad852014-06-05 23:13:36 -07001101 if (!obj) {
1102 return;
1103 }
Markus Armbruster719a3072018-06-08 19:02:31 +02001104 g_assert(obj->ref > 0);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001105
1106 /* parent always holds a reference to its children */
Jan Kiszkaf08c03f2013-07-02 11:36:39 +02001107 if (atomic_fetch_dec(&obj->ref) == 1) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001108 object_finalize(obj);
1109 }
1110}
1111
Paolo Bonzini64607d02014-06-05 13:11:51 +02001112ObjectProperty *
1113object_property_add(Object *obj, const char *name, const char *type,
1114 ObjectPropertyAccessor *get,
1115 ObjectPropertyAccessor *set,
1116 ObjectPropertyRelease *release,
1117 void *opaque, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001118{
Peter Maydell54852b02013-03-25 13:15:13 +00001119 ObjectProperty *prop;
Peter Crosthwaite33965902014-08-19 23:55:52 -07001120 size_t name_len = strlen(name);
1121
1122 if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
1123 int i;
1124 ObjectProperty *ret;
1125 char *name_no_array = g_strdup(name);
1126
1127 name_no_array[name_len - 3] = '\0';
1128 for (i = 0; ; ++i) {
1129 char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
1130
1131 ret = object_property_add(obj, full_name, type, get, set,
1132 release, opaque, NULL);
1133 g_free(full_name);
1134 if (ret) {
1135 break;
1136 }
1137 }
1138 g_free(name_no_array);
1139 return ret;
1140 }
Peter Maydell54852b02013-03-25 13:15:13 +00001141
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001142 if (object_property_find(obj, name, NULL) != NULL) {
Greg Kurzd55e9372019-11-04 14:23:55 +01001143 error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
1144 name, object_get_typename(obj));
Pavel Fedinb604a852015-10-13 13:37:45 +01001145 return NULL;
Peter Maydell54852b02013-03-25 13:15:13 +00001146 }
1147
1148 prop = g_malloc0(sizeof(*prop));
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001149
1150 prop->name = g_strdup(name);
1151 prop->type = g_strdup(type);
1152
1153 prop->get = get;
1154 prop->set = set;
1155 prop->release = release;
1156 prop->opaque = opaque;
1157
Pavel Fedinb604a852015-10-13 13:37:45 +01001158 g_hash_table_insert(obj->properties, prop->name, prop);
Paolo Bonzini64607d02014-06-05 13:11:51 +02001159 return prop;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001160}
1161
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001162ObjectProperty *
1163object_class_property_add(ObjectClass *klass,
1164 const char *name,
1165 const char *type,
1166 ObjectPropertyAccessor *get,
1167 ObjectPropertyAccessor *set,
1168 ObjectPropertyRelease *release,
1169 void *opaque,
1170 Error **errp)
1171{
1172 ObjectProperty *prop;
1173
1174 if (object_class_property_find(klass, name, NULL) != NULL) {
Greg Kurzd55e9372019-11-04 14:23:55 +01001175 error_setg(errp, "attempt to add duplicate property '%s' to class (type '%s')",
1176 name, object_class_get_name(klass));
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001177 return NULL;
1178 }
1179
1180 prop = g_malloc0(sizeof(*prop));
1181
1182 prop->name = g_strdup(name);
1183 prop->type = g_strdup(type);
1184
1185 prop->get = get;
1186 prop->set = set;
1187 prop->release = release;
1188 prop->opaque = opaque;
1189
1190 g_hash_table_insert(klass->properties, g_strdup(name), prop);
1191
1192 return prop;
1193}
1194
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001195ObjectProperty *object_property_find(Object *obj, const char *name,
1196 Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001197{
1198 ObjectProperty *prop;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001199 ObjectClass *klass = object_get_class(obj);
1200
1201 prop = object_class_property_find(klass, name, NULL);
1202 if (prop) {
1203 return prop;
1204 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001205
Pavel Fedinb604a852015-10-13 13:37:45 +01001206 prop = g_hash_table_lookup(obj->properties, name);
1207 if (prop) {
1208 return prop;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001209 }
1210
Cole Robinsonf231b882014-03-21 19:42:26 -04001211 error_setg(errp, "Property '.%s' not found", name);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001212 return NULL;
1213}
1214
Daniel P. Berrange7746abd2015-12-09 12:34:02 +00001215void object_property_iter_init(ObjectPropertyIterator *iter,
1216 Object *obj)
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001217{
Daniel P. Berrange7746abd2015-12-09 12:34:02 +00001218 g_hash_table_iter_init(&iter->iter, obj->properties);
1219 iter->nextclass = object_get_class(obj);
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001220}
1221
1222ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1223{
Pavel Fedinb604a852015-10-13 13:37:45 +01001224 gpointer key, val;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001225 while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
1226 if (!iter->nextclass) {
1227 return NULL;
1228 }
1229 g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
1230 iter->nextclass = object_class_get_parent(iter->nextclass);
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001231 }
Pavel Fedinb604a852015-10-13 13:37:45 +01001232 return val;
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001233}
1234
Alexey Kardashevskiy961c47b2018-03-02 00:09:39 +11001235void object_class_property_iter_init(ObjectPropertyIterator *iter,
1236 ObjectClass *klass)
1237{
1238 g_hash_table_iter_init(&iter->iter, klass->properties);
Marc-André Lureau684546d2018-09-06 17:37:36 +04001239 iter->nextclass = object_class_get_parent(klass);
Alexey Kardashevskiy961c47b2018-03-02 00:09:39 +11001240}
1241
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001242ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
1243 Error **errp)
1244{
1245 ObjectProperty *prop;
1246 ObjectClass *parent_klass;
1247
1248 parent_klass = object_class_get_parent(klass);
1249 if (parent_klass) {
1250 prop = object_class_property_find(parent_klass, name, NULL);
1251 if (prop) {
1252 return prop;
1253 }
1254 }
1255
1256 prop = g_hash_table_lookup(klass->properties, name);
1257 if (!prop) {
1258 error_setg(errp, "Property '.%s' not found", name);
1259 }
1260 return prop;
1261}
1262
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001263void object_property_del(Object *obj, const char *name, Error **errp)
1264{
Pavel Fedinb604a852015-10-13 13:37:45 +01001265 ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1266
1267 if (!prop) {
1268 error_setg(errp, "Property '.%s' not found", name);
Anthony Liguori0866aca2011-12-23 15:34:39 -06001269 return;
1270 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001271
Anthony Liguori0866aca2011-12-23 15:34:39 -06001272 if (prop->release) {
1273 prop->release(obj, name, prop->opaque);
1274 }
Pavel Fedinb604a852015-10-13 13:37:45 +01001275 g_hash_table_remove(obj->properties, name);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001276}
1277
1278void object_property_get(Object *obj, Visitor *v, const char *name,
1279 Error **errp)
1280{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001281 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001282 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001283 return;
1284 }
1285
1286 if (!prop->get) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001287 error_setg(errp, QERR_PERMISSION_DENIED);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001288 } else {
Eric Blaked7bce992016-01-29 06:48:55 -07001289 prop->get(obj, v, name, prop->opaque, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001290 }
1291}
1292
1293void object_property_set(Object *obj, Visitor *v, const char *name,
1294 Error **errp)
1295{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001296 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001297 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001298 return;
1299 }
1300
1301 if (!prop->set) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001302 error_setg(errp, QERR_PERMISSION_DENIED);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001303 } else {
Eric Blaked7bce992016-01-29 06:48:55 -07001304 prop->set(obj, v, name, prop->opaque, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001305 }
1306}
1307
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001308void object_property_set_str(Object *obj, const char *value,
1309 const char *name, Error **errp)
1310{
1311 QString *qstr = qstring_from_str(value);
1312 object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
1313
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001314 qobject_unref(qstr);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001315}
1316
1317char *object_property_get_str(Object *obj, const char *name,
1318 Error **errp)
1319{
1320 QObject *ret = object_property_get_qobject(obj, name, errp);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001321 char *retval;
1322
1323 if (!ret) {
1324 return NULL;
1325 }
Peter Xuaafb21a2018-03-09 16:59:47 +08001326
1327 retval = g_strdup(qobject_get_try_str(ret));
1328 if (!retval) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001329 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001330 }
1331
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001332 qobject_unref(ret);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001333 return retval;
1334}
1335
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001336void object_property_set_link(Object *obj, Object *value,
1337 const char *name, Error **errp)
1338{
Peter Crosthwaited3c49312014-09-25 22:19:19 -07001339 if (value) {
1340 gchar *path = object_get_canonical_path(value);
1341 object_property_set_str(obj, path, name, errp);
1342 g_free(path);
1343 } else {
1344 object_property_set_str(obj, "", name, errp);
1345 }
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001346}
1347
1348Object *object_property_get_link(Object *obj, const char *name,
1349 Error **errp)
1350{
1351 char *str = object_property_get_str(obj, name, errp);
1352 Object *target = NULL;
1353
1354 if (str && *str) {
1355 target = object_resolve_path(str, NULL);
1356 if (!target) {
Markus Armbruster75158eb2015-03-16 08:57:47 +01001357 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1358 "Device '%s' not found", str);
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001359 }
1360 }
1361
1362 g_free(str);
1363 return target;
1364}
1365
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001366void object_property_set_bool(Object *obj, bool value,
1367 const char *name, Error **errp)
1368{
Eric Blakefc48ffc2015-05-15 16:24:59 -06001369 QBool *qbool = qbool_from_bool(value);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001370 object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
1371
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001372 qobject_unref(qbool);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001373}
1374
1375bool object_property_get_bool(Object *obj, const char *name,
1376 Error **errp)
1377{
1378 QObject *ret = object_property_get_qobject(obj, name, errp);
1379 QBool *qbool;
1380 bool retval;
1381
1382 if (!ret) {
1383 return false;
1384 }
Max Reitz7dc847e2018-02-24 16:40:29 +01001385 qbool = qobject_to(QBool, ret);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001386 if (!qbool) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001387 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001388 retval = false;
1389 } else {
Eric Blakefc48ffc2015-05-15 16:24:59 -06001390 retval = qbool_get_bool(qbool);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001391 }
1392
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001393 qobject_unref(ret);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001394 return retval;
1395}
1396
1397void object_property_set_int(Object *obj, int64_t value,
1398 const char *name, Error **errp)
1399{
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001400 QNum *qnum = qnum_from_int(value);
1401 object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001402
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001403 qobject_unref(qnum);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001404}
1405
1406int64_t object_property_get_int(Object *obj, const char *name,
1407 Error **errp)
1408{
1409 QObject *ret = object_property_get_qobject(obj, name, errp);
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001410 QNum *qnum;
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001411 int64_t retval;
1412
1413 if (!ret) {
1414 return -1;
1415 }
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001416
Max Reitz7dc847e2018-02-24 16:40:29 +01001417 qnum = qobject_to(QNum, ret);
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001418 if (!qnum || !qnum_get_try_int(qnum, &retval)) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001419 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001420 retval = -1;
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001421 }
1422
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001423 qobject_unref(ret);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001424 return retval;
1425}
1426
Marc-André Lureau31527792017-06-07 20:36:04 +04001427void object_property_set_uint(Object *obj, uint64_t value,
1428 const char *name, Error **errp)
1429{
1430 QNum *qnum = qnum_from_uint(value);
1431
1432 object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001433 qobject_unref(qnum);
Marc-André Lureau31527792017-06-07 20:36:04 +04001434}
1435
1436uint64_t object_property_get_uint(Object *obj, const char *name,
1437 Error **errp)
1438{
1439 QObject *ret = object_property_get_qobject(obj, name, errp);
1440 QNum *qnum;
1441 uint64_t retval;
1442
1443 if (!ret) {
1444 return 0;
1445 }
Max Reitz7dc847e2018-02-24 16:40:29 +01001446 qnum = qobject_to(QNum, ret);
Marc-André Lureau31527792017-06-07 20:36:04 +04001447 if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
1448 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
1449 retval = 0;
1450 }
1451
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001452 qobject_unref(ret);
Marc-André Lureau31527792017-06-07 20:36:04 +04001453 return retval;
1454}
1455
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001456typedef struct EnumProperty {
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02001457 const QEnumLookup *lookup;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001458 int (*get)(Object *, Error **);
1459 void (*set)(Object *, int, Error **);
1460} EnumProperty;
1461
Hu Tao1f217722014-05-14 17:43:33 +08001462int object_property_get_enum(Object *obj, const char *name,
Daniel P. Berrangea3590da2015-05-27 16:07:56 +01001463 const char *typename, Error **errp)
Hu Tao1f217722014-05-14 17:43:33 +08001464{
Markus Armbruster4715d422015-08-25 20:00:45 +02001465 Error *err = NULL;
Eric Blake7a0525c2016-06-09 10:48:37 -06001466 Visitor *v;
Chen Fan976620a2014-08-18 14:46:34 +08001467 char *str;
Hu Tao1f217722014-05-14 17:43:33 +08001468 int ret;
Daniel P. Berrangea3590da2015-05-27 16:07:56 +01001469 ObjectProperty *prop = object_property_find(obj, name, errp);
1470 EnumProperty *enumprop;
1471
1472 if (prop == NULL) {
1473 return 0;
1474 }
1475
1476 if (!g_str_equal(prop->type, typename)) {
1477 error_setg(errp, "Property %s on %s is not '%s' enum type",
1478 name, object_class_get_name(
1479 object_get_class(obj)), typename);
1480 return 0;
1481 }
1482
1483 enumprop = prop->opaque;
Hu Tao1f217722014-05-14 17:43:33 +08001484
Eric Blake3b098d52016-06-09 10:48:43 -06001485 v = string_output_visitor_new(false, &str);
Eric Blakee7ca5652016-06-09 10:48:39 -06001486 object_property_get(obj, v, name, &err);
Markus Armbruster4715d422015-08-25 20:00:45 +02001487 if (err) {
1488 error_propagate(errp, err);
Eric Blakee7ca5652016-06-09 10:48:39 -06001489 visit_free(v);
Markus Armbruster4715d422015-08-25 20:00:45 +02001490 return 0;
1491 }
Eric Blake3b098d52016-06-09 10:48:43 -06001492 visit_complete(v, &str);
Eric Blakee7ca5652016-06-09 10:48:39 -06001493 visit_free(v);
Eric Blake7a0525c2016-06-09 10:48:37 -06001494 v = string_input_visitor_new(str);
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02001495 visit_type_enum(v, name, &ret, enumprop->lookup, errp);
Chen Fan976620a2014-08-18 14:46:34 +08001496
1497 g_free(str);
Eric Blake7a0525c2016-06-09 10:48:37 -06001498 visit_free(v);
Hu Tao1f217722014-05-14 17:43:33 +08001499
1500 return ret;
1501}
1502
1503void object_property_get_uint16List(Object *obj, const char *name,
1504 uint16List **list, Error **errp)
1505{
Markus Armbruster4715d422015-08-25 20:00:45 +02001506 Error *err = NULL;
Eric Blake7a0525c2016-06-09 10:48:37 -06001507 Visitor *v;
Chen Fan976620a2014-08-18 14:46:34 +08001508 char *str;
Hu Tao1f217722014-05-14 17:43:33 +08001509
Eric Blake3b098d52016-06-09 10:48:43 -06001510 v = string_output_visitor_new(false, &str);
1511 object_property_get(obj, v, name, &err);
Markus Armbruster4715d422015-08-25 20:00:45 +02001512 if (err) {
1513 error_propagate(errp, err);
1514 goto out;
1515 }
Eric Blake3b098d52016-06-09 10:48:43 -06001516 visit_complete(v, &str);
1517 visit_free(v);
Eric Blake7a0525c2016-06-09 10:48:37 -06001518 v = string_input_visitor_new(str);
1519 visit_type_uint16List(v, NULL, list, errp);
Chen Fan976620a2014-08-18 14:46:34 +08001520
1521 g_free(str);
Markus Armbruster4715d422015-08-25 20:00:45 +02001522out:
Eric Blake3b098d52016-06-09 10:48:43 -06001523 visit_free(v);
Hu Tao1f217722014-05-14 17:43:33 +08001524}
1525
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001526void object_property_parse(Object *obj, const char *string,
1527 const char *name, Error **errp)
1528{
Eric Blake7a0525c2016-06-09 10:48:37 -06001529 Visitor *v = string_input_visitor_new(string);
1530 object_property_set(obj, v, name, errp);
1531 visit_free(v);
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001532}
1533
Paolo Bonzini0b7593e2014-02-08 11:01:50 +01001534char *object_property_print(Object *obj, const char *name, bool human,
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001535 Error **errp)
1536{
Eric Blake3b098d52016-06-09 10:48:43 -06001537 Visitor *v;
Gonglei3a530092014-09-27 13:13:55 +08001538 char *string = NULL;
1539 Error *local_err = NULL;
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001540
Eric Blake3b098d52016-06-09 10:48:43 -06001541 v = string_output_visitor_new(human, &string);
1542 object_property_get(obj, v, name, &local_err);
Gonglei3a530092014-09-27 13:13:55 +08001543 if (local_err) {
1544 error_propagate(errp, local_err);
1545 goto out;
1546 }
1547
Eric Blake3b098d52016-06-09 10:48:43 -06001548 visit_complete(v, &string);
Gonglei3a530092014-09-27 13:13:55 +08001549
1550out:
Eric Blake3b098d52016-06-09 10:48:43 -06001551 visit_free(v);
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001552 return string;
1553}
1554
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001555const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1556{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001557 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001558 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001559 return NULL;
1560 }
1561
1562 return prop->type;
1563}
1564
1565Object *object_get_root(void)
1566{
Anthony Liguori8b45d442011-12-23 09:08:05 -06001567 static Object *root;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001568
Anthony Liguori8b45d442011-12-23 09:08:05 -06001569 if (!root) {
1570 root = object_new("container");
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001571 }
1572
Anthony Liguori8b45d442011-12-23 09:08:05 -06001573 return root;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001574}
1575
Daniel P. Berrangebc2256c2015-05-13 17:14:05 +01001576Object *object_get_objects_root(void)
1577{
1578 return container_get(object_get_root(), "/objects");
1579}
1580
Peter Xu7c47c4e2017-09-28 10:59:54 +08001581Object *object_get_internal_root(void)
1582{
1583 static Object *internal_root;
1584
1585 if (!internal_root) {
1586 internal_root = object_new("container");
1587 }
1588
1589 return internal_root;
1590}
1591
Eric Blaked7bce992016-01-29 06:48:55 -07001592static void object_get_child_property(Object *obj, Visitor *v,
1593 const char *name, void *opaque,
1594 Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001595{
1596 Object *child = opaque;
1597 gchar *path;
1598
1599 path = object_get_canonical_path(child);
Eric Blake51e72bc2016-01-29 06:48:54 -07001600 visit_type_str(v, name, &path, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001601 g_free(path);
1602}
1603
Paolo Bonzini64607d02014-06-05 13:11:51 +02001604static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
1605{
1606 return opaque;
1607}
1608
Anthony Liguoridb85b572011-12-23 08:47:39 -06001609static void object_finalize_child_property(Object *obj, const char *name,
1610 void *opaque)
1611{
1612 Object *child = opaque;
1613
Paolo Bonzinibffc6872014-06-11 11:57:38 +02001614 if (child->class->unparent) {
1615 (child->class->unparent)(child);
1616 }
1617 child->parent = NULL;
Anthony Liguoridb85b572011-12-23 08:47:39 -06001618 object_unref(child);
1619}
1620
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001621void object_property_add_child(Object *obj, const char *name,
1622 Object *child, Error **errp)
1623{
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001624 Error *local_err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001625 gchar *type;
Paolo Bonzini64607d02014-06-05 13:11:51 +02001626 ObjectProperty *op;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001627
Peter Crosthwaite8faa2f82014-09-25 22:19:52 -07001628 if (child->parent != NULL) {
1629 error_setg(errp, "child object is already parented");
1630 return;
1631 }
1632
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001633 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
1634
Paolo Bonzini64607d02014-06-05 13:11:51 +02001635 op = object_property_add(obj, name, type, object_get_child_property, NULL,
1636 object_finalize_child_property, child, &local_err);
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001637 if (local_err) {
1638 error_propagate(errp, local_err);
1639 goto out;
1640 }
Paolo Bonzini64607d02014-06-05 13:11:51 +02001641
1642 op->resolve = object_resolve_child_property;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001643 object_ref(child);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001644 child->parent = obj;
1645
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001646out:
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001647 g_free(type);
1648}
1649
Igor Mammedov8f5d58e2017-07-14 10:14:50 +08001650void object_property_allow_set_link(const Object *obj, const char *name,
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001651 Object *val, Error **errp)
1652{
1653 /* Allow the link to be set, always */
1654}
1655
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001656typedef struct {
1657 Object **child;
Igor Mammedov8f5d58e2017-07-14 10:14:50 +08001658 void (*check)(const Object *, const char *, Object *, Error **);
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001659 ObjectPropertyLinkFlags flags;
1660} LinkProperty;
1661
Eric Blaked7bce992016-01-29 06:48:55 -07001662static void object_get_link_property(Object *obj, Visitor *v,
1663 const char *name, void *opaque,
1664 Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001665{
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001666 LinkProperty *lprop = opaque;
1667 Object **child = lprop->child;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001668 gchar *path;
1669
1670 if (*child) {
1671 path = object_get_canonical_path(*child);
Eric Blake51e72bc2016-01-29 06:48:54 -07001672 visit_type_str(v, name, &path, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001673 g_free(path);
1674 } else {
1675 path = (gchar *)"";
Eric Blake51e72bc2016-01-29 06:48:54 -07001676 visit_type_str(v, name, &path, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001677 }
1678}
1679
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001680/*
1681 * object_resolve_link:
1682 *
1683 * Lookup an object and ensure its type matches the link property type. This
1684 * is similar to object_resolve_path() except type verification against the
1685 * link property is performed.
1686 *
1687 * Returns: The matched object or NULL on path lookup failures.
1688 */
1689static Object *object_resolve_link(Object *obj, const char *name,
1690 const char *path, Error **errp)
1691{
1692 const char *type;
1693 gchar *target_type;
1694 bool ambiguous = false;
1695 Object *target;
1696
1697 /* Go from link<FOO> to FOO. */
1698 type = object_property_get_type(obj, name, NULL);
1699 target_type = g_strndup(&type[5], strlen(type) - 6);
1700 target = object_resolve_path_type(path, target_type, &ambiguous);
1701
1702 if (ambiguous) {
Eric Blake455b0fd2015-11-10 23:51:20 -07001703 error_setg(errp, "Path '%s' does not uniquely identify an object",
1704 path);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001705 } else if (!target) {
1706 target = object_resolve_path(path, &ambiguous);
1707 if (target || ambiguous) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001708 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001709 } else {
Markus Armbruster75158eb2015-03-16 08:57:47 +01001710 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1711 "Device '%s' not found", path);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001712 }
1713 target = NULL;
1714 }
1715 g_free(target_type);
1716
1717 return target;
1718}
1719
Eric Blaked7bce992016-01-29 06:48:55 -07001720static void object_set_link_property(Object *obj, Visitor *v,
1721 const char *name, void *opaque,
1722 Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001723{
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001724 Error *local_err = NULL;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001725 LinkProperty *prop = opaque;
1726 Object **child = prop->child;
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001727 Object *old_target = *child;
1728 Object *new_target = NULL;
1729 char *path = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001730
Eric Blake51e72bc2016-01-29 06:48:54 -07001731 visit_type_str(v, name, &path, &local_err);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001732
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001733 if (!local_err && strcmp(path, "") != 0) {
1734 new_target = object_resolve_link(obj, name, path, &local_err);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001735 }
1736
1737 g_free(path);
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001738 if (local_err) {
1739 error_propagate(errp, local_err);
1740 return;
1741 }
Alexander Barabashf0cdc962012-02-22 19:22:26 +02001742
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001743 prop->check(obj, name, new_target, &local_err);
1744 if (local_err) {
1745 error_propagate(errp, local_err);
1746 return;
1747 }
1748
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001749 *child = new_target;
Marc-André Lureau265b5782018-05-31 21:51:17 +02001750 if (prop->flags == OBJ_PROP_LINK_STRONG) {
1751 object_ref(new_target);
1752 object_unref(old_target);
1753 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001754}
1755
Paolo Bonzini64607d02014-06-05 13:11:51 +02001756static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
1757{
1758 LinkProperty *lprop = opaque;
1759
1760 return *lprop->child;
1761}
1762
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001763static void object_release_link_property(Object *obj, const char *name,
1764 void *opaque)
1765{
1766 LinkProperty *prop = opaque;
1767
Marc-André Lureau265b5782018-05-31 21:51:17 +02001768 if ((prop->flags & OBJ_PROP_LINK_STRONG) && *prop->child) {
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001769 object_unref(*prop->child);
1770 }
1771 g_free(prop);
1772}
1773
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001774void object_property_add_link(Object *obj, const char *name,
1775 const char *type, Object **child,
Igor Mammedov8f5d58e2017-07-14 10:14:50 +08001776 void (*check)(const Object *, const char *,
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001777 Object *, Error **),
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001778 ObjectPropertyLinkFlags flags,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001779 Error **errp)
1780{
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001781 Error *local_err = NULL;
1782 LinkProperty *prop = g_malloc(sizeof(*prop));
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001783 gchar *full_type;
Paolo Bonzini64607d02014-06-05 13:11:51 +02001784 ObjectProperty *op;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001785
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001786 prop->child = child;
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001787 prop->check = check;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001788 prop->flags = flags;
1789
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001790 full_type = g_strdup_printf("link<%s>", type);
1791
Paolo Bonzini64607d02014-06-05 13:11:51 +02001792 op = object_property_add(obj, name, full_type,
1793 object_get_link_property,
1794 check ? object_set_link_property : NULL,
1795 object_release_link_property,
1796 prop,
1797 &local_err);
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001798 if (local_err) {
1799 error_propagate(errp, local_err);
1800 g_free(prop);
Paolo Bonzini64607d02014-06-05 13:11:51 +02001801 goto out;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001802 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001803
Paolo Bonzini64607d02014-06-05 13:11:51 +02001804 op->resolve = object_resolve_link_property;
1805
1806out:
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001807 g_free(full_type);
1808}
1809
Paolo Bonzinifb9e7e32015-05-05 18:29:00 +02001810void object_property_add_const_link(Object *obj, const char *name,
1811 Object *target, Error **errp)
1812{
1813 char *link_type;
1814 ObjectProperty *op;
1815
1816 link_type = g_strdup_printf("link<%s>", object_get_typename(target));
1817 op = object_property_add(obj, name, link_type,
1818 object_get_child_property, NULL,
1819 NULL, target, errp);
1820 if (op != NULL) {
1821 op->resolve = object_resolve_child_property;
1822 }
1823 g_free(link_type);
1824}
1825
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001826gchar *object_get_canonical_path_component(Object *obj)
1827{
1828 ObjectProperty *prop = NULL;
Pavel Fedinb604a852015-10-13 13:37:45 +01001829 GHashTableIter iter;
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001830
Paolo Bonzini770dec22018-04-30 11:44:17 +02001831 if (obj->parent == NULL) {
1832 return NULL;
1833 }
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001834
Pavel Fedinb604a852015-10-13 13:37:45 +01001835 g_hash_table_iter_init(&iter, obj->parent->properties);
1836 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001837 if (!object_property_is_child(prop)) {
1838 continue;
1839 }
1840
1841 if (prop->opaque == obj) {
1842 return g_strdup(prop->name);
1843 }
1844 }
1845
1846 /* obj had a parent but was not a child, should never happen */
1847 g_assert_not_reached();
1848 return NULL;
1849}
1850
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001851gchar *object_get_canonical_path(Object *obj)
1852{
1853 Object *root = object_get_root();
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001854 char *newpath, *path = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001855
Paolo Bonzinie40077f2018-05-30 18:16:04 +02001856 if (obj == root) {
1857 return g_strdup("/");
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001858 }
1859
Paolo Bonzinie40077f2018-05-30 18:16:04 +02001860 do {
1861 char *component = object_get_canonical_path_component(obj);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001862
Paolo Bonzinie40077f2018-05-30 18:16:04 +02001863 if (!component) {
1864 /* A canonical path must be complete, so discard what was
1865 * collected so far.
1866 */
1867 g_free(path);
1868 return NULL;
1869 }
1870
1871 newpath = g_strdup_printf("/%s%s", component, path ? path : "");
1872 g_free(path);
1873 g_free(component);
1874 path = newpath;
1875 obj = obj->parent;
1876 } while (obj != root);
1877
1878 return path;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001879}
1880
Andreas Färber3e84b482013-01-15 02:55:10 +01001881Object *object_resolve_path_component(Object *parent, const gchar *part)
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001882{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001883 ObjectProperty *prop = object_property_find(parent, part, NULL);
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001884 if (prop == NULL) {
1885 return NULL;
1886 }
1887
Paolo Bonzini64607d02014-06-05 13:11:51 +02001888 if (prop->resolve) {
1889 return prop->resolve(parent, prop->opaque, part);
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001890 } else {
1891 return NULL;
1892 }
1893}
1894
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001895static Object *object_resolve_abs_path(Object *parent,
1896 gchar **parts,
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001897 const char *typename,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001898 int index)
1899{
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001900 Object *child;
1901
1902 if (parts[index] == NULL) {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001903 return object_dynamic_cast(parent, typename);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001904 }
1905
1906 if (strcmp(parts[index], "") == 0) {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001907 return object_resolve_abs_path(parent, parts, typename, index + 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001908 }
1909
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001910 child = object_resolve_path_component(parent, parts[index]);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001911 if (!child) {
1912 return NULL;
1913 }
1914
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001915 return object_resolve_abs_path(child, parts, typename, index + 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001916}
1917
1918static Object *object_resolve_partial_path(Object *parent,
1919 gchar **parts,
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001920 const char *typename,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001921 bool *ambiguous)
1922{
1923 Object *obj;
Pavel Fedinb604a852015-10-13 13:37:45 +01001924 GHashTableIter iter;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001925 ObjectProperty *prop;
1926
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001927 obj = object_resolve_abs_path(parent, parts, typename, 0);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001928
Pavel Fedinb604a852015-10-13 13:37:45 +01001929 g_hash_table_iter_init(&iter, parent->properties);
1930 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001931 Object *found;
1932
Andreas Färber5d9d3f42012-05-27 00:32:40 +02001933 if (!object_property_is_child(prop)) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001934 continue;
1935 }
1936
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001937 found = object_resolve_partial_path(prop->opaque, parts,
1938 typename, ambiguous);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001939 if (found) {
1940 if (obj) {
Eduardo Habkostebcc4792017-07-07 18:30:52 -03001941 *ambiguous = true;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001942 return NULL;
1943 }
1944 obj = found;
1945 }
1946
Eduardo Habkostebcc4792017-07-07 18:30:52 -03001947 if (*ambiguous) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001948 return NULL;
1949 }
1950 }
1951
1952 return obj;
1953}
1954
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001955Object *object_resolve_path_type(const char *path, const char *typename,
Eduardo Habkostebcc4792017-07-07 18:30:52 -03001956 bool *ambiguousp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001957{
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001958 Object *obj;
1959 gchar **parts;
1960
1961 parts = g_strsplit(path, "/", 0);
Paolo Bonzini2e1103f2013-04-18 18:44:02 +02001962 assert(parts);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001963
Paolo Bonzini2e1103f2013-04-18 18:44:02 +02001964 if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
Eduardo Habkostebcc4792017-07-07 18:30:52 -03001965 bool ambiguous = false;
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001966 obj = object_resolve_partial_path(object_get_root(), parts,
Eduardo Habkostebcc4792017-07-07 18:30:52 -03001967 typename, &ambiguous);
1968 if (ambiguousp) {
1969 *ambiguousp = ambiguous;
1970 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001971 } else {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001972 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001973 }
1974
1975 g_strfreev(parts);
1976
1977 return obj;
1978}
1979
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001980Object *object_resolve_path(const char *path, bool *ambiguous)
1981{
1982 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1983}
1984
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001985typedef struct StringProperty
1986{
1987 char *(*get)(Object *, Error **);
1988 void (*set)(Object *, const char *, Error **);
1989} StringProperty;
1990
Eric Blaked7bce992016-01-29 06:48:55 -07001991static void property_get_str(Object *obj, Visitor *v, const char *name,
1992 void *opaque, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001993{
1994 StringProperty *prop = opaque;
1995 char *value;
Markus Armbrustere1c82372015-08-25 20:00:46 +02001996 Error *err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001997
Markus Armbrustere1c82372015-08-25 20:00:46 +02001998 value = prop->get(obj, &err);
1999 if (err) {
2000 error_propagate(errp, err);
2001 return;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002002 }
Markus Armbrustere1c82372015-08-25 20:00:46 +02002003
Eric Blake51e72bc2016-01-29 06:48:54 -07002004 visit_type_str(v, name, &value, errp);
Markus Armbrustere1c82372015-08-25 20:00:46 +02002005 g_free(value);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002006}
2007
Eric Blaked7bce992016-01-29 06:48:55 -07002008static void property_set_str(Object *obj, Visitor *v, const char *name,
2009 void *opaque, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002010{
2011 StringProperty *prop = opaque;
2012 char *value;
2013 Error *local_err = NULL;
2014
Eric Blake51e72bc2016-01-29 06:48:54 -07002015 visit_type_str(v, name, &value, &local_err);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002016 if (local_err) {
2017 error_propagate(errp, local_err);
2018 return;
2019 }
2020
2021 prop->set(obj, value, errp);
2022 g_free(value);
2023}
2024
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01002025static void property_release_str(Object *obj, const char *name,
2026 void *opaque)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002027{
2028 StringProperty *prop = opaque;
2029 g_free(prop);
2030}
2031
2032void object_property_add_str(Object *obj, const char *name,
2033 char *(*get)(Object *, Error **),
2034 void (*set)(Object *, const char *, Error **),
2035 Error **errp)
2036{
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01002037 Error *local_err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002038 StringProperty *prop = g_malloc0(sizeof(*prop));
2039
2040 prop->get = get;
2041 prop->set = set;
2042
2043 object_property_add(obj, name, "string",
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01002044 get ? property_get_str : NULL,
2045 set ? property_set_str : NULL,
2046 property_release_str,
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01002047 prop, &local_err);
2048 if (local_err) {
2049 error_propagate(errp, local_err);
2050 g_free(prop);
2051 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06002052}
Paolo Bonzini745549c2012-03-31 16:45:54 +02002053
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002054void object_class_property_add_str(ObjectClass *klass, const char *name,
2055 char *(*get)(Object *, Error **),
2056 void (*set)(Object *, const char *,
2057 Error **),
2058 Error **errp)
2059{
2060 Error *local_err = NULL;
2061 StringProperty *prop = g_malloc0(sizeof(*prop));
2062
2063 prop->get = get;
2064 prop->set = set;
2065
2066 object_class_property_add(klass, name, "string",
2067 get ? property_get_str : NULL,
2068 set ? property_set_str : NULL,
2069 property_release_str,
2070 prop, &local_err);
2071 if (local_err) {
2072 error_propagate(errp, local_err);
2073 g_free(prop);
2074 }
2075}
2076
Anthony Liguori0e558842012-06-25 10:32:46 -05002077typedef struct BoolProperty
2078{
2079 bool (*get)(Object *, Error **);
2080 void (*set)(Object *, bool, Error **);
2081} BoolProperty;
2082
Eric Blaked7bce992016-01-29 06:48:55 -07002083static void property_get_bool(Object *obj, Visitor *v, const char *name,
2084 void *opaque, Error **errp)
Anthony Liguori0e558842012-06-25 10:32:46 -05002085{
2086 BoolProperty *prop = opaque;
2087 bool value;
Markus Armbruster4715d422015-08-25 20:00:45 +02002088 Error *err = NULL;
Anthony Liguori0e558842012-06-25 10:32:46 -05002089
Markus Armbruster4715d422015-08-25 20:00:45 +02002090 value = prop->get(obj, &err);
2091 if (err) {
2092 error_propagate(errp, err);
2093 return;
2094 }
2095
Eric Blake51e72bc2016-01-29 06:48:54 -07002096 visit_type_bool(v, name, &value, errp);
Anthony Liguori0e558842012-06-25 10:32:46 -05002097}
2098
Eric Blaked7bce992016-01-29 06:48:55 -07002099static void property_set_bool(Object *obj, Visitor *v, const char *name,
2100 void *opaque, Error **errp)
Anthony Liguori0e558842012-06-25 10:32:46 -05002101{
2102 BoolProperty *prop = opaque;
2103 bool value;
2104 Error *local_err = NULL;
2105
Eric Blake51e72bc2016-01-29 06:48:54 -07002106 visit_type_bool(v, name, &value, &local_err);
Anthony Liguori0e558842012-06-25 10:32:46 -05002107 if (local_err) {
2108 error_propagate(errp, local_err);
2109 return;
2110 }
2111
2112 prop->set(obj, value, errp);
2113}
2114
2115static void property_release_bool(Object *obj, const char *name,
2116 void *opaque)
2117{
2118 BoolProperty *prop = opaque;
2119 g_free(prop);
2120}
2121
2122void object_property_add_bool(Object *obj, const char *name,
2123 bool (*get)(Object *, Error **),
2124 void (*set)(Object *, bool, Error **),
2125 Error **errp)
2126{
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01002127 Error *local_err = NULL;
Anthony Liguori0e558842012-06-25 10:32:46 -05002128 BoolProperty *prop = g_malloc0(sizeof(*prop));
2129
2130 prop->get = get;
2131 prop->set = set;
2132
2133 object_property_add(obj, name, "bool",
2134 get ? property_get_bool : NULL,
2135 set ? property_set_bool : NULL,
2136 property_release_bool,
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01002137 prop, &local_err);
2138 if (local_err) {
2139 error_propagate(errp, local_err);
2140 g_free(prop);
2141 }
Anthony Liguori0e558842012-06-25 10:32:46 -05002142}
2143
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002144void object_class_property_add_bool(ObjectClass *klass, const char *name,
2145 bool (*get)(Object *, Error **),
2146 void (*set)(Object *, bool, Error **),
2147 Error **errp)
2148{
2149 Error *local_err = NULL;
2150 BoolProperty *prop = g_malloc0(sizeof(*prop));
2151
2152 prop->get = get;
2153 prop->set = set;
2154
2155 object_class_property_add(klass, name, "bool",
2156 get ? property_get_bool : NULL,
2157 set ? property_set_bool : NULL,
2158 property_release_bool,
2159 prop, &local_err);
2160 if (local_err) {
2161 error_propagate(errp, local_err);
2162 g_free(prop);
2163 }
2164}
2165
Eric Blaked7bce992016-01-29 06:48:55 -07002166static void property_get_enum(Object *obj, Visitor *v, const char *name,
2167 void *opaque, Error **errp)
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002168{
2169 EnumProperty *prop = opaque;
2170 int value;
Markus Armbruster4715d422015-08-25 20:00:45 +02002171 Error *err = NULL;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002172
Markus Armbruster4715d422015-08-25 20:00:45 +02002173 value = prop->get(obj, &err);
2174 if (err) {
2175 error_propagate(errp, err);
2176 return;
2177 }
2178
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002179 visit_type_enum(v, name, &value, prop->lookup, errp);
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002180}
2181
Eric Blaked7bce992016-01-29 06:48:55 -07002182static void property_set_enum(Object *obj, Visitor *v, const char *name,
2183 void *opaque, Error **errp)
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002184{
2185 EnumProperty *prop = opaque;
2186 int value;
Markus Armbruster4715d422015-08-25 20:00:45 +02002187 Error *err = NULL;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002188
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002189 visit_type_enum(v, name, &value, prop->lookup, &err);
Markus Armbruster4715d422015-08-25 20:00:45 +02002190 if (err) {
2191 error_propagate(errp, err);
2192 return;
2193 }
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002194 prop->set(obj, value, errp);
2195}
2196
2197static void property_release_enum(Object *obj, const char *name,
2198 void *opaque)
2199{
2200 EnumProperty *prop = opaque;
2201 g_free(prop);
2202}
2203
2204void object_property_add_enum(Object *obj, const char *name,
2205 const char *typename,
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002206 const QEnumLookup *lookup,
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002207 int (*get)(Object *, Error **),
2208 void (*set)(Object *, int, Error **),
2209 Error **errp)
2210{
2211 Error *local_err = NULL;
2212 EnumProperty *prop = g_malloc(sizeof(*prop));
2213
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002214 prop->lookup = lookup;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01002215 prop->get = get;
2216 prop->set = set;
2217
2218 object_property_add(obj, name, typename,
2219 get ? property_get_enum : NULL,
2220 set ? property_set_enum : NULL,
2221 property_release_enum,
2222 prop, &local_err);
2223 if (local_err) {
2224 error_propagate(errp, local_err);
2225 g_free(prop);
2226 }
2227}
2228
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002229void object_class_property_add_enum(ObjectClass *klass, const char *name,
2230 const char *typename,
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002231 const QEnumLookup *lookup,
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002232 int (*get)(Object *, Error **),
2233 void (*set)(Object *, int, Error **),
2234 Error **errp)
2235{
2236 Error *local_err = NULL;
2237 EnumProperty *prop = g_malloc(sizeof(*prop));
2238
Marc-André Lureauf7abe0e2017-08-24 10:46:10 +02002239 prop->lookup = lookup;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002240 prop->get = get;
2241 prop->set = set;
2242
2243 object_class_property_add(klass, name, typename,
2244 get ? property_get_enum : NULL,
2245 set ? property_set_enum : NULL,
2246 property_release_enum,
2247 prop, &local_err);
2248 if (local_err) {
2249 error_propagate(errp, local_err);
2250 g_free(prop);
2251 }
2252}
2253
David Gibson8e099d12015-02-06 14:55:45 +11002254typedef struct TMProperty {
2255 void (*get)(Object *, struct tm *, Error **);
2256} TMProperty;
2257
Eric Blaked7bce992016-01-29 06:48:55 -07002258static void property_get_tm(Object *obj, Visitor *v, const char *name,
2259 void *opaque, Error **errp)
David Gibson8e099d12015-02-06 14:55:45 +11002260{
2261 TMProperty *prop = opaque;
2262 Error *err = NULL;
2263 struct tm value;
2264
2265 prop->get(obj, &value, &err);
2266 if (err) {
2267 goto out;
2268 }
2269
Eric Blake337283d2016-01-29 06:48:57 -07002270 visit_start_struct(v, name, NULL, 0, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002271 if (err) {
2272 goto out;
2273 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002274 visit_type_int32(v, "tm_year", &value.tm_year, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002275 if (err) {
2276 goto out_end;
2277 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002278 visit_type_int32(v, "tm_mon", &value.tm_mon, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002279 if (err) {
2280 goto out_end;
2281 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002282 visit_type_int32(v, "tm_mday", &value.tm_mday, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002283 if (err) {
2284 goto out_end;
2285 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002286 visit_type_int32(v, "tm_hour", &value.tm_hour, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002287 if (err) {
2288 goto out_end;
2289 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002290 visit_type_int32(v, "tm_min", &value.tm_min, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002291 if (err) {
2292 goto out_end;
2293 }
Eric Blake51e72bc2016-01-29 06:48:54 -07002294 visit_type_int32(v, "tm_sec", &value.tm_sec, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002295 if (err) {
2296 goto out_end;
2297 }
Eric Blake15c2f662016-04-28 15:45:27 -06002298 visit_check_struct(v, &err);
David Gibson8e099d12015-02-06 14:55:45 +11002299out_end:
Eric Blake1158bb22016-06-09 10:48:34 -06002300 visit_end_struct(v, NULL);
David Gibson8e099d12015-02-06 14:55:45 +11002301out:
2302 error_propagate(errp, err);
2303
2304}
2305
2306static void property_release_tm(Object *obj, const char *name,
2307 void *opaque)
2308{
2309 TMProperty *prop = opaque;
2310 g_free(prop);
2311}
2312
2313void object_property_add_tm(Object *obj, const char *name,
2314 void (*get)(Object *, struct tm *, Error **),
2315 Error **errp)
2316{
2317 Error *local_err = NULL;
2318 TMProperty *prop = g_malloc0(sizeof(*prop));
2319
2320 prop->get = get;
2321
2322 object_property_add(obj, name, "struct tm",
2323 get ? property_get_tm : NULL, NULL,
2324 property_release_tm,
2325 prop, &local_err);
2326 if (local_err) {
2327 error_propagate(errp, local_err);
2328 g_free(prop);
2329 }
2330}
2331
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002332void object_class_property_add_tm(ObjectClass *klass, const char *name,
2333 void (*get)(Object *, struct tm *, Error **),
2334 Error **errp)
2335{
2336 Error *local_err = NULL;
2337 TMProperty *prop = g_malloc0(sizeof(*prop));
2338
2339 prop->get = get;
2340
2341 object_class_property_add(klass, name, "struct tm",
2342 get ? property_get_tm : NULL, NULL,
2343 property_release_tm,
2344 prop, &local_err);
2345 if (local_err) {
2346 error_propagate(errp, local_err);
2347 g_free(prop);
2348 }
2349}
2350
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002351static char *qdev_get_type(Object *obj, Error **errp)
2352{
2353 return g_strdup(object_get_typename(obj));
2354}
2355
Eric Blaked7bce992016-01-29 06:48:55 -07002356static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2357 void *opaque, Error **errp)
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002358{
2359 uint8_t value = *(uint8_t *)opaque;
Eric Blake51e72bc2016-01-29 06:48:54 -07002360 visit_type_uint8(v, name, &value, errp);
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002361}
2362
Eric Blaked7bce992016-01-29 06:48:55 -07002363static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2364 void *opaque, Error **errp)
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002365{
2366 uint16_t value = *(uint16_t *)opaque;
Eric Blake51e72bc2016-01-29 06:48:54 -07002367 visit_type_uint16(v, name, &value, errp);
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002368}
2369
Eric Blaked7bce992016-01-29 06:48:55 -07002370static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2371 void *opaque, Error **errp)
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002372{
2373 uint32_t value = *(uint32_t *)opaque;
Eric Blake51e72bc2016-01-29 06:48:54 -07002374 visit_type_uint32(v, name, &value, errp);
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002375}
2376
Eric Blaked7bce992016-01-29 06:48:55 -07002377static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2378 void *opaque, Error **errp)
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002379{
2380 uint64_t value = *(uint64_t *)opaque;
Eric Blake51e72bc2016-01-29 06:48:54 -07002381 visit_type_uint64(v, name, &value, errp);
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002382}
2383
2384void object_property_add_uint8_ptr(Object *obj, const char *name,
2385 const uint8_t *v, Error **errp)
2386{
2387 object_property_add(obj, name, "uint8", property_get_uint8_ptr,
2388 NULL, NULL, (void *)v, errp);
2389}
2390
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002391void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2392 const uint8_t *v, Error **errp)
2393{
2394 object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
2395 NULL, NULL, (void *)v, errp);
2396}
2397
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002398void object_property_add_uint16_ptr(Object *obj, const char *name,
2399 const uint16_t *v, Error **errp)
2400{
2401 object_property_add(obj, name, "uint16", property_get_uint16_ptr,
2402 NULL, NULL, (void *)v, errp);
2403}
2404
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002405void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2406 const uint16_t *v, Error **errp)
2407{
2408 object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
2409 NULL, NULL, (void *)v, errp);
2410}
2411
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002412void object_property_add_uint32_ptr(Object *obj, const char *name,
2413 const uint32_t *v, Error **errp)
2414{
2415 object_property_add(obj, name, "uint32", property_get_uint32_ptr,
2416 NULL, NULL, (void *)v, errp);
2417}
2418
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002419void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2420 const uint32_t *v, Error **errp)
2421{
2422 object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
2423 NULL, NULL, (void *)v, errp);
2424}
2425
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002426void object_property_add_uint64_ptr(Object *obj, const char *name,
2427 const uint64_t *v, Error **errp)
2428{
2429 object_property_add(obj, name, "uint64", property_get_uint64_ptr,
2430 NULL, NULL, (void *)v, errp);
2431}
2432
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002433void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2434 const uint64_t *v, Error **errp)
2435{
2436 object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
2437 NULL, NULL, (void *)v, errp);
2438}
2439
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002440typedef struct {
2441 Object *target_obj;
Eduardo Habkost1590d262015-04-09 16:57:29 -03002442 char *target_name;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002443} AliasProperty;
2444
Eric Blaked7bce992016-01-29 06:48:55 -07002445static void property_get_alias(Object *obj, Visitor *v, const char *name,
2446 void *opaque, Error **errp)
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002447{
2448 AliasProperty *prop = opaque;
2449
2450 object_property_get(prop->target_obj, v, prop->target_name, errp);
2451}
2452
Eric Blaked7bce992016-01-29 06:48:55 -07002453static void property_set_alias(Object *obj, Visitor *v, const char *name,
2454 void *opaque, Error **errp)
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002455{
2456 AliasProperty *prop = opaque;
2457
2458 object_property_set(prop->target_obj, v, prop->target_name, errp);
2459}
2460
Paolo Bonzini64607d02014-06-05 13:11:51 +02002461static Object *property_resolve_alias(Object *obj, void *opaque,
2462 const gchar *part)
2463{
2464 AliasProperty *prop = opaque;
2465
2466 return object_resolve_path_component(prop->target_obj, prop->target_name);
2467}
2468
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002469static void property_release_alias(Object *obj, const char *name, void *opaque)
2470{
2471 AliasProperty *prop = opaque;
2472
Eduardo Habkost1590d262015-04-09 16:57:29 -03002473 g_free(prop->target_name);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002474 g_free(prop);
2475}
2476
2477void object_property_add_alias(Object *obj, const char *name,
2478 Object *target_obj, const char *target_name,
2479 Error **errp)
2480{
2481 AliasProperty *prop;
Paolo Bonzini64607d02014-06-05 13:11:51 +02002482 ObjectProperty *op;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002483 ObjectProperty *target_prop;
Paolo Bonzinid1906982014-06-10 11:17:35 +02002484 gchar *prop_type;
Gonglei8ae9a9e2014-09-27 13:13:56 +08002485 Error *local_err = NULL;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002486
2487 target_prop = object_property_find(target_obj, target_name, errp);
2488 if (!target_prop) {
2489 return;
2490 }
2491
Paolo Bonzinid1906982014-06-10 11:17:35 +02002492 if (object_property_is_child(target_prop)) {
2493 prop_type = g_strdup_printf("link%s",
2494 target_prop->type + strlen("child"));
2495 } else {
2496 prop_type = g_strdup(target_prop->type);
2497 }
2498
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002499 prop = g_malloc(sizeof(*prop));
2500 prop->target_obj = target_obj;
Eduardo Habkost1590d262015-04-09 16:57:29 -03002501 prop->target_name = g_strdup(target_name);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002502
Paolo Bonzinid1906982014-06-10 11:17:35 +02002503 op = object_property_add(obj, name, prop_type,
Paolo Bonzini64607d02014-06-05 13:11:51 +02002504 property_get_alias,
2505 property_set_alias,
2506 property_release_alias,
Gonglei8ae9a9e2014-09-27 13:13:56 +08002507 prop, &local_err);
2508 if (local_err) {
2509 error_propagate(errp, local_err);
2510 g_free(prop);
2511 goto out;
2512 }
Paolo Bonzini64607d02014-06-05 13:11:51 +02002513 op->resolve = property_resolve_alias;
Paolo Bonzinid1906982014-06-10 11:17:35 +02002514
Andreas Färbera18bb412015-03-27 17:34:10 +01002515 object_property_set_description(obj, op->name,
Gonglei80742642014-10-07 14:33:21 +08002516 target_prop->description,
2517 &error_abort);
2518
Gonglei8ae9a9e2014-09-27 13:13:56 +08002519out:
Paolo Bonzinid1906982014-06-10 11:17:35 +02002520 g_free(prop_type);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002521}
2522
Gonglei80742642014-10-07 14:33:21 +08002523void object_property_set_description(Object *obj, const char *name,
2524 const char *description, Error **errp)
2525{
2526 ObjectProperty *op;
2527
2528 op = object_property_find(obj, name, errp);
2529 if (!op) {
2530 return;
2531 }
2532
2533 g_free(op->description);
2534 op->description = g_strdup(description);
2535}
2536
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002537void object_class_property_set_description(ObjectClass *klass,
2538 const char *name,
2539 const char *description,
2540 Error **errp)
2541{
2542 ObjectProperty *op;
2543
2544 op = g_hash_table_lookup(klass->properties, name);
2545 if (!op) {
2546 error_setg(errp, "Property '.%s' not found", name);
2547 return;
2548 }
2549
2550 g_free(op->description);
2551 op->description = g_strdup(description);
2552}
2553
Marc-André Lureau7439a032018-09-06 18:09:32 +04002554static void object_class_init(ObjectClass *klass, void *data)
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002555{
Marc-André Lureau7439a032018-09-06 18:09:32 +04002556 object_class_property_add_str(klass, "type", qdev_get_type,
2557 NULL, &error_abort);
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002558}
2559
Paolo Bonzini745549c2012-03-31 16:45:54 +02002560static void register_types(void)
2561{
2562 static TypeInfo interface_info = {
2563 .name = TYPE_INTERFACE,
Anthony Liguori33e95c62012-08-10 13:16:10 +10002564 .class_size = sizeof(InterfaceClass),
Paolo Bonzini745549c2012-03-31 16:45:54 +02002565 .abstract = true,
2566 };
2567
2568 static TypeInfo object_info = {
2569 .name = TYPE_OBJECT,
2570 .instance_size = sizeof(Object),
Marc-André Lureau7439a032018-09-06 18:09:32 +04002571 .class_init = object_class_init,
Paolo Bonzini745549c2012-03-31 16:45:54 +02002572 .abstract = true,
2573 };
2574
Paolo Bonzini049cb3c2012-04-04 15:58:40 +02002575 type_interface = type_register_internal(&interface_info);
2576 type_register_internal(&object_info);
Paolo Bonzini745549c2012-03-31 16:45:54 +02002577}
2578
2579type_init(register_types)