blob: 5d4c80b102c83f5dcc1461260e62bb39a90c1aeb [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
Paolo Bonzini14cccb62012-12-17 18:19:50 +010013#include "qom/object.h"
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +010014#include "qom/object_interfaces.h"
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060015#include "qemu-common.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010016#include "qapi/visitor.h"
Hu Tao1f217722014-05-14 17:43:33 +080017#include "qapi-visit.h"
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +010018#include "qapi/string-input-visitor.h"
19#include "qapi/string-output-visitor.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010020#include "qapi/qmp/qerror.h"
Paolo Bonzinifa131d92013-05-10 14:16:39 +020021#include "trace.h"
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060022
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +010023/* TODO: replace QObject with a simpler visitor to avoid a dependency
24 * of the QOM core on QObject? */
Paolo Bonzini14cccb62012-12-17 18:19:50 +010025#include "qom/qom-qobject.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010026#include "qapi/qmp/qobject.h"
27#include "qapi/qmp/qbool.h"
28#include "qapi/qmp/qint.h"
29#include "qapi/qmp/qstring.h"
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +010030
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060031#define MAX_INTERFACES 32
32
33typedef struct InterfaceImpl InterfaceImpl;
34typedef struct TypeImpl TypeImpl;
35
36struct InterfaceImpl
37{
Anthony Liguori33e95c62012-08-10 13:16:10 +100038 const char *typename;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060039};
40
41struct TypeImpl
42{
43 const char *name;
44
45 size_t class_size;
46
47 size_t instance_size;
48
49 void (*class_init)(ObjectClass *klass, void *data);
Paolo Bonzini3b50e312012-05-02 13:30:55 +020050 void (*class_base_init)(ObjectClass *klass, void *data);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060051 void (*class_finalize)(ObjectClass *klass, void *data);
52
53 void *class_data;
54
55 void (*instance_init)(Object *obj);
Eduardo Habkost8231c2d2013-07-10 17:08:41 -030056 void (*instance_post_init)(Object *obj);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060057 void (*instance_finalize)(Object *obj);
58
59 bool abstract;
60
61 const char *parent;
62 TypeImpl *parent_type;
63
64 ObjectClass *class;
65
66 int num_interfaces;
67 InterfaceImpl interfaces[MAX_INTERFACES];
68};
69
Daniel P. Berrangea00c9482015-10-13 13:37:40 +010070struct ObjectPropertyIterator {
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +010071 ObjectClass *nextclass;
Pavel Fedinb604a852015-10-13 13:37:45 +010072 GHashTableIter iter;
Daniel P. Berrangea00c9482015-10-13 13:37:40 +010073};
74
Paolo Bonzini9970bd82012-02-03 11:51:39 +010075static Type type_interface;
76
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060077static GHashTable *type_table_get(void)
78{
79 static GHashTable *type_table;
80
81 if (type_table == NULL) {
82 type_table = g_hash_table_new(g_str_hash, g_str_equal);
83 }
84
85 return type_table;
86}
87
Hervé Poussineauf54c19c2013-12-03 16:42:00 +010088static bool enumerating_types;
89
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060090static void type_table_add(TypeImpl *ti)
91{
Hervé Poussineauf54c19c2013-12-03 16:42:00 +010092 assert(!enumerating_types);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -060093 g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
94}
95
96static TypeImpl *type_table_lookup(const char *name)
97{
98 return g_hash_table_lookup(type_table_get(), name);
99}
100
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100101static TypeImpl *type_new(const TypeInfo *info)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600102{
103 TypeImpl *ti = g_malloc0(sizeof(*ti));
Anthony Liguori33e95c62012-08-10 13:16:10 +1000104 int i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600105
106 g_assert(info->name != NULL);
107
Anthony Liguori73093352012-01-25 13:37:36 -0600108 if (type_table_lookup(info->name) != NULL) {
109 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
110 abort();
111 }
112
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600113 ti->name = g_strdup(info->name);
114 ti->parent = g_strdup(info->parent);
115
116 ti->class_size = info->class_size;
117 ti->instance_size = info->instance_size;
118
119 ti->class_init = info->class_init;
Paolo Bonzini3b50e312012-05-02 13:30:55 +0200120 ti->class_base_init = info->class_base_init;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600121 ti->class_finalize = info->class_finalize;
122 ti->class_data = info->class_data;
123
124 ti->instance_init = info->instance_init;
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300125 ti->instance_post_init = info->instance_post_init;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600126 ti->instance_finalize = info->instance_finalize;
127
128 ti->abstract = info->abstract;
129
Anthony Liguori33e95c62012-08-10 13:16:10 +1000130 for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
131 ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600132 }
Anthony Liguori33e95c62012-08-10 13:16:10 +1000133 ti->num_interfaces = i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600134
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100135 return ti;
136}
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600137
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100138static TypeImpl *type_register_internal(const TypeInfo *info)
139{
140 TypeImpl *ti;
141 ti = type_new(info);
142
143 type_table_add(ti);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600144 return ti;
145}
146
Paolo Bonzini049cb3c2012-04-04 15:58:40 +0200147TypeImpl *type_register(const TypeInfo *info)
148{
149 assert(info->parent);
150 return type_register_internal(info);
151}
152
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600153TypeImpl *type_register_static(const TypeInfo *info)
154{
155 return type_register(info);
156}
157
158static TypeImpl *type_get_by_name(const char *name)
159{
160 if (name == NULL) {
161 return NULL;
162 }
163
164 return type_table_lookup(name);
165}
166
167static TypeImpl *type_get_parent(TypeImpl *type)
168{
169 if (!type->parent_type && type->parent) {
170 type->parent_type = type_get_by_name(type->parent);
171 g_assert(type->parent_type != NULL);
172 }
173
174 return type->parent_type;
175}
176
177static bool type_has_parent(TypeImpl *type)
178{
179 return (type->parent != NULL);
180}
181
182static size_t type_class_get_size(TypeImpl *ti)
183{
184 if (ti->class_size) {
185 return ti->class_size;
186 }
187
188 if (type_has_parent(ti)) {
189 return type_class_get_size(type_get_parent(ti));
190 }
191
192 return sizeof(ObjectClass);
193}
194
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400195static size_t type_object_get_size(TypeImpl *ti)
196{
197 if (ti->instance_size) {
198 return ti->instance_size;
199 }
200
201 if (type_has_parent(ti)) {
202 return type_object_get_size(type_get_parent(ti));
203 }
204
205 return 0;
206}
207
Anthony Liguori33e95c62012-08-10 13:16:10 +1000208static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600209{
Anthony Liguori33e95c62012-08-10 13:16:10 +1000210 assert(target_type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600211
Cao jinb30d8052015-11-03 10:36:42 +0800212 /* Check if target_type is a direct ancestor of type */
Anthony Liguori33e95c62012-08-10 13:16:10 +1000213 while (type) {
214 if (type == target_type) {
215 return true;
216 }
217
218 type = type_get_parent(type);
219 }
220
221 return false;
222}
223
224static void type_initialize(TypeImpl *ti);
225
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100226static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
227 TypeImpl *parent_type)
Anthony Liguori33e95c62012-08-10 13:16:10 +1000228{
229 InterfaceClass *new_iface;
230 TypeInfo info = { };
231 TypeImpl *iface_impl;
232
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100233 info.parent = parent_type->name;
234 info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000235 info.abstract = true;
236
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100237 iface_impl = type_new(&info);
238 iface_impl->parent_type = parent_type;
Anthony Liguori33e95c62012-08-10 13:16:10 +1000239 type_initialize(iface_impl);
240 g_free((char *)info.name);
241
242 new_iface = (InterfaceClass *)iface_impl->class;
243 new_iface->concrete_class = ti->class;
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100244 new_iface->interface_type = interface_type;
Anthony Liguori33e95c62012-08-10 13:16:10 +1000245
246 ti->class->interfaces = g_slist_append(ti->class->interfaces,
247 iface_impl->class);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600248}
249
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100250static void object_property_free(gpointer data)
251{
252 ObjectProperty *prop = data;
253
254 g_free(prop->name);
255 g_free(prop->type);
256 g_free(prop->description);
257 g_free(prop);
258}
259
Igor Mitsyankoac451032012-02-28 15:57:11 +0400260static void type_initialize(TypeImpl *ti)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600261{
Paolo Bonzini745549c2012-03-31 16:45:54 +0200262 TypeImpl *parent;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600263
264 if (ti->class) {
265 return;
266 }
267
268 ti->class_size = type_class_get_size(ti);
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400269 ti->instance_size = type_object_get_size(ti);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600270
271 ti->class = g_malloc0(ti->class_size);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600272
Paolo Bonzini745549c2012-03-31 16:45:54 +0200273 parent = type_get_parent(ti);
274 if (parent) {
Igor Mitsyankoac451032012-02-28 15:57:11 +0400275 type_initialize(parent);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000276 GSList *e;
277 int i;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600278
Andreas Färber8438a132015-11-16 17:49:20 +0100279 g_assert_cmpint(parent->class_size, <=, ti->class_size);
Paolo Bonzini745549c2012-03-31 16:45:54 +0200280 memcpy(ti->class, parent->class, parent->class_size);
Peter Crosthwaite3e407de2013-02-19 14:02:09 +1000281 ti->class->interfaces = NULL;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100282 ti->class->properties = g_hash_table_new_full(
283 g_str_hash, g_str_equal, g_free, object_property_free);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000284
285 for (e = parent->class->interfaces; e; e = e->next) {
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100286 InterfaceClass *iface = e->data;
287 ObjectClass *klass = OBJECT_CLASS(iface);
288
289 type_initialize_interface(ti, iface->interface_type, klass->type);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000290 }
291
292 for (i = 0; i < ti->num_interfaces; i++) {
293 TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
294 for (e = ti->class->interfaces; e; e = e->next) {
295 TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
296
297 if (type_is_ancestor(target_type, t)) {
298 break;
299 }
300 }
301
302 if (e) {
303 continue;
304 }
305
Paolo Bonzinib061dc42013-12-03 16:41:59 +0100306 type_initialize_interface(ti, t, t);
Anthony Liguori33e95c62012-08-10 13:16:10 +1000307 }
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100308 } else {
309 ti->class->properties = g_hash_table_new_full(
310 g_str_hash, g_str_equal, g_free, object_property_free);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600311 }
312
Paolo Bonzini745549c2012-03-31 16:45:54 +0200313 ti->class->type = ti;
314
315 while (parent) {
316 if (parent->class_base_init) {
317 parent->class_base_init(ti->class, ti->class_data);
318 }
319 parent = type_get_parent(parent);
320 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600321
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600322 if (ti->class_init) {
323 ti->class_init(ti->class, ti->class_data);
324 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600325}
326
327static void object_init_with_type(Object *obj, TypeImpl *ti)
328{
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600329 if (type_has_parent(ti)) {
330 object_init_with_type(obj, type_get_parent(ti));
331 }
332
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600333 if (ti->instance_init) {
334 ti->instance_init(obj);
335 }
336}
337
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300338static void object_post_init_with_type(Object *obj, TypeImpl *ti)
339{
340 if (ti->instance_post_init) {
341 ti->instance_post_init(obj);
342 }
343
344 if (type_has_parent(ti)) {
345 object_post_init_with_type(obj, type_get_parent(ti));
346 }
347}
348
Andreas Färber5b9237f2013-08-30 18:28:37 +0200349void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600350{
351 Object *obj = data;
352
353 g_assert(type != NULL);
Igor Mitsyankoac451032012-02-28 15:57:11 +0400354 type_initialize(type);
Igor Mitsyankoaca59af2012-02-28 15:57:10 +0400355
Andreas Färber8438a132015-11-16 17:49:20 +0100356 g_assert_cmpint(type->instance_size, >=, sizeof(Object));
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600357 g_assert(type->abstract == false);
Andreas Färber8438a132015-11-16 17:49:20 +0100358 g_assert_cmpint(size, >=, type->instance_size);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600359
360 memset(obj, 0, type->instance_size);
361 obj->class = type->class;
Paolo Bonzini764b6312012-11-23 09:47:12 +0100362 object_ref(obj);
Pavel Fedinb604a852015-10-13 13:37:45 +0100363 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
364 NULL, object_property_free);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600365 object_init_with_type(obj, type);
Eduardo Habkost8231c2d2013-07-10 17:08:41 -0300366 object_post_init_with_type(obj, type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600367}
368
Andreas Färber213f0c42013-08-23 19:37:12 +0200369void object_initialize(void *data, size_t size, const char *typename)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600370{
371 TypeImpl *type = type_get_by_name(typename);
372
Andreas Färber5b9237f2013-08-30 18:28:37 +0200373 object_initialize_with_type(data, size, type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600374}
375
Andreas Färber5d9d3f42012-05-27 00:32:40 +0200376static inline bool object_property_is_child(ObjectProperty *prop)
377{
378 return strstart(prop->type, "child<", NULL);
379}
380
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600381static void object_property_del_all(Object *obj)
382{
Pavel Fedinb604a852015-10-13 13:37:45 +0100383 ObjectProperty *prop;
384 GHashTableIter iter;
385 gpointer key, value;
386 bool released;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600387
Pavel Fedinb604a852015-10-13 13:37:45 +0100388 do {
389 released = false;
390 g_hash_table_iter_init(&iter, obj->properties);
391 while (g_hash_table_iter_next(&iter, &key, &value)) {
392 prop = value;
393 if (prop->release) {
394 prop->release(obj, prop->name, prop->opaque);
395 prop->release = NULL;
396 released = true;
397 break;
398 }
399 g_hash_table_iter_remove(&iter);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600400 }
Pavel Fedinb604a852015-10-13 13:37:45 +0100401 } while (released);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600402
Pavel Fedinb604a852015-10-13 13:37:45 +0100403 g_hash_table_unref(obj->properties);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600404}
405
406static void object_property_del_child(Object *obj, Object *child, Error **errp)
407{
408 ObjectProperty *prop;
Pavel Fedinb604a852015-10-13 13:37:45 +0100409 GHashTableIter iter;
410 gpointer key, value;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600411
Pavel Fedinb604a852015-10-13 13:37:45 +0100412 g_hash_table_iter_init(&iter, obj->properties);
413 while (g_hash_table_iter_next(&iter, &key, &value)) {
414 prop = value;
Andreas Färber5d9d3f42012-05-27 00:32:40 +0200415 if (object_property_is_child(prop) && prop->opaque == child) {
Pavel Fedinb604a852015-10-13 13:37:45 +0100416 if (prop->release) {
417 prop->release(obj, prop->name, prop->opaque);
418 prop->release = NULL;
419 }
420 break;
421 }
422 }
423 g_hash_table_iter_init(&iter, obj->properties);
424 while (g_hash_table_iter_next(&iter, &key, &value)) {
425 prop = value;
426 if (object_property_is_child(prop) && prop->opaque == child) {
427 g_hash_table_iter_remove(&iter);
Paolo Bonzini6c1fdcf2012-02-28 09:54:15 +0100428 break;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600429 }
430 }
431}
432
433void object_unparent(Object *obj)
434{
Michael S. Tsirkine998fa82013-03-18 21:01:37 +0200435 if (obj->parent) {
436 object_property_del_child(obj->parent, obj, NULL);
437 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600438}
439
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600440static void object_deinit(Object *obj, TypeImpl *type)
441{
442 if (type->instance_finalize) {
443 type->instance_finalize(obj);
444 }
445
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600446 if (type_has_parent(type)) {
447 object_deinit(obj, type_get_parent(type));
448 }
449}
450
Paolo Bonzini339c2702012-11-23 09:47:16 +0100451static void object_finalize(void *data)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600452{
453 Object *obj = data;
454 TypeImpl *ti = obj->class->type;
455
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600456 object_property_del_all(obj);
Paolo Bonzini76a6e1c2014-06-11 11:58:30 +0200457 object_deinit(obj, ti);
Anthony Liguoridb85b572011-12-23 08:47:39 -0600458
Andreas Färber8438a132015-11-16 17:49:20 +0100459 g_assert_cmpint(obj->ref, ==, 0);
Paolo Bonzinifde9bf42012-11-23 09:47:14 +0100460 if (obj->free) {
461 obj->free(obj);
462 }
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600463}
464
465Object *object_new_with_type(Type type)
466{
467 Object *obj;
468
469 g_assert(type != NULL);
Igor Mitsyankoac451032012-02-28 15:57:11 +0400470 type_initialize(type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600471
472 obj = g_malloc(type->instance_size);
Andreas Färber5b9237f2013-08-30 18:28:37 +0200473 object_initialize_with_type(obj, type->instance_size, type);
Paolo Bonzinifde9bf42012-11-23 09:47:14 +0100474 obj->free = g_free;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600475
476 return obj;
477}
478
479Object *object_new(const char *typename)
480{
481 TypeImpl *ti = type_get_by_name(typename);
482
483 return object_new_with_type(ti);
484}
485
Daniel P. Berrangea31bdae2015-05-13 17:14:06 +0100486
487Object *object_new_with_props(const char *typename,
488 Object *parent,
489 const char *id,
490 Error **errp,
491 ...)
492{
493 va_list vargs;
494 Object *obj;
495
496 va_start(vargs, errp);
497 obj = object_new_with_propv(typename, parent, id, errp, vargs);
498 va_end(vargs);
499
500 return obj;
501}
502
503
504Object *object_new_with_propv(const char *typename,
505 Object *parent,
506 const char *id,
507 Error **errp,
508 va_list vargs)
509{
510 Object *obj;
511 ObjectClass *klass;
512 Error *local_err = NULL;
513
514 klass = object_class_by_name(typename);
515 if (!klass) {
516 error_setg(errp, "invalid object type: %s", typename);
517 return NULL;
518 }
519
520 if (object_class_is_abstract(klass)) {
521 error_setg(errp, "object type '%s' is abstract", typename);
522 return NULL;
523 }
524 obj = object_new(typename);
525
526 if (object_set_propv(obj, &local_err, vargs) < 0) {
527 goto error;
528 }
529
530 object_property_add_child(parent, id, obj, &local_err);
531 if (local_err) {
532 goto error;
533 }
534
535 if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
536 user_creatable_complete(obj, &local_err);
537 if (local_err) {
538 object_unparent(obj);
539 goto error;
540 }
541 }
542
543 object_unref(OBJECT(obj));
544 return obj;
545
546 error:
547 if (local_err) {
548 error_propagate(errp, local_err);
549 }
550 object_unref(obj);
551 return NULL;
552}
553
554
555int object_set_props(Object *obj,
556 Error **errp,
557 ...)
558{
559 va_list vargs;
560 int ret;
561
562 va_start(vargs, errp);
563 ret = object_set_propv(obj, errp, vargs);
564 va_end(vargs);
565
566 return ret;
567}
568
569
570int object_set_propv(Object *obj,
571 Error **errp,
572 va_list vargs)
573{
574 const char *propname;
575 Error *local_err = NULL;
576
577 propname = va_arg(vargs, char *);
578 while (propname != NULL) {
579 const char *value = va_arg(vargs, char *);
580
581 g_assert(value != NULL);
582 object_property_parse(obj, value, propname, &local_err);
583 if (local_err) {
584 error_propagate(errp, local_err);
585 return -1;
586 }
587 propname = va_arg(vargs, char *);
588 }
589
590 return 0;
591}
592
593
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600594Object *object_dynamic_cast(Object *obj, const char *typename)
595{
Paolo Bonzinib7f43fe2012-11-23 16:56:17 +0100596 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
Paolo Bonziniacc4af32012-02-03 11:57:23 +0100597 return obj;
598 }
599
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600600 return NULL;
601}
602
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200603Object *object_dynamic_cast_assert(Object *obj, const char *typename,
604 const char *file, int line, const char *func)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600605{
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200606 trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
607 typename, file, line, func);
608
Paolo Bonzini3556c232013-05-10 14:16:40 +0200609#ifdef CONFIG_QOM_CAST_DEBUG
Anthony Liguori03587322013-05-13 15:22:24 -0500610 int i;
611 Object *inst;
612
Peter Crosthwaite95916ab2013-05-22 11:19:16 +1000613 for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800614 if (obj->class->object_cast_cache[i] == typename) {
Anthony Liguori03587322013-05-13 15:22:24 -0500615 goto out;
616 }
617 }
618
619 inst = object_dynamic_cast(obj, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600620
Paolo Bonzinib7f43fe2012-11-23 16:56:17 +0100621 if (!inst && obj) {
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200622 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
623 file, line, func, obj, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600624 abort();
625 }
626
Paolo Bonzini3556c232013-05-10 14:16:40 +0200627 assert(obj == inst);
Anthony Liguori03587322013-05-13 15:22:24 -0500628
Peter Crosthwaite95916ab2013-05-22 11:19:16 +1000629 if (obj && obj == inst) {
Anthony Liguori03587322013-05-13 15:22:24 -0500630 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800631 obj->class->object_cast_cache[i - 1] =
632 obj->class->object_cast_cache[i];
Anthony Liguori03587322013-05-13 15:22:24 -0500633 }
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800634 obj->class->object_cast_cache[i - 1] = typename;
Anthony Liguori03587322013-05-13 15:22:24 -0500635 }
636
637out:
Paolo Bonzini3556c232013-05-10 14:16:40 +0200638#endif
639 return obj;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600640}
641
642ObjectClass *object_class_dynamic_cast(ObjectClass *class,
643 const char *typename)
644{
Anthony Liguori33e95c62012-08-10 13:16:10 +1000645 ObjectClass *ret = NULL;
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200646 TypeImpl *target_type;
647 TypeImpl *type;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600648
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200649 if (!class) {
650 return NULL;
651 }
652
Paolo Bonzini793c96b2013-05-10 14:16:37 +0200653 /* A simple fast path that can trigger a lot for leaf classes. */
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200654 type = class->type;
Paolo Bonzini793c96b2013-05-10 14:16:37 +0200655 if (type->name == typename) {
656 return class;
657 }
658
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200659 target_type = type_get_by_name(typename);
Alexander Graf9ab880b2013-04-30 15:02:16 +0200660 if (!target_type) {
661 /* target class type unknown, so fail the cast */
662 return NULL;
663 }
664
Peter Crosthwaite00e2cea2013-02-19 14:02:10 +1000665 if (type->class->interfaces &&
666 type_is_ancestor(target_type, type_interface)) {
Anthony Liguori33e95c62012-08-10 13:16:10 +1000667 int found = 0;
668 GSList *i;
669
670 for (i = class->interfaces; i; i = i->next) {
671 ObjectClass *target_class = i->data;
672
673 if (type_is_ancestor(target_class->type, target_type)) {
674 ret = target_class;
675 found++;
676 }
677 }
678
679 /* The match was ambiguous, don't allow a cast */
680 if (found > 1) {
681 ret = NULL;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600682 }
Anthony Liguori33e95c62012-08-10 13:16:10 +1000683 } else if (type_is_ancestor(type, target_type)) {
684 ret = class;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600685 }
686
Anthony Liguori33e95c62012-08-10 13:16:10 +1000687 return ret;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600688}
689
690ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200691 const char *typename,
692 const char *file, int line,
693 const char *func)
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600694{
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200695 ObjectClass *ret;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600696
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200697 trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
698 typename, file, line, func);
699
Anthony Liguori03587322013-05-13 15:22:24 -0500700#ifdef CONFIG_QOM_CAST_DEBUG
701 int i;
702
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000703 for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800704 if (class->class_cast_cache[i] == typename) {
Anthony Liguori03587322013-05-13 15:22:24 -0500705 ret = class;
706 goto out;
707 }
708 }
709#else
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000710 if (!class || !class->interfaces) {
Paolo Bonzini3556c232013-05-10 14:16:40 +0200711 return class;
712 }
713#endif
714
Paolo Bonzinifa131d92013-05-10 14:16:39 +0200715 ret = object_class_dynamic_cast(class, typename);
Paolo Bonzinibf0fda32013-05-10 14:16:36 +0200716 if (!ret && class) {
Paolo Bonzinibe17f182013-05-10 14:16:38 +0200717 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
718 file, line, func, class, typename);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600719 abort();
720 }
721
Anthony Liguori03587322013-05-13 15:22:24 -0500722#ifdef CONFIG_QOM_CAST_DEBUG
Peter Crosthwaite9d6a3d52013-06-18 19:18:59 +1000723 if (class && ret == class) {
Anthony Liguori03587322013-05-13 15:22:24 -0500724 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800725 class->class_cast_cache[i - 1] = class->class_cast_cache[i];
Anthony Liguori03587322013-05-13 15:22:24 -0500726 }
Peter Crosthwaite0ab4c942013-11-27 20:27:33 -0800727 class->class_cast_cache[i - 1] = typename;
Anthony Liguori03587322013-05-13 15:22:24 -0500728 }
729out:
730#endif
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600731 return ret;
732}
733
734const char *object_get_typename(Object *obj)
735{
736 return obj->class->type->name;
737}
738
739ObjectClass *object_get_class(Object *obj)
740{
741 return obj->class;
742}
743
Andreas Färber17862372013-01-23 12:20:18 +0100744bool object_class_is_abstract(ObjectClass *klass)
745{
746 return klass->type->abstract;
747}
748
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600749const char *object_class_get_name(ObjectClass *klass)
750{
751 return klass->type->name;
752}
753
754ObjectClass *object_class_by_name(const char *typename)
755{
756 TypeImpl *type = type_get_by_name(typename);
757
758 if (!type) {
759 return NULL;
760 }
761
Igor Mitsyankoac451032012-02-28 15:57:11 +0400762 type_initialize(type);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600763
764 return type->class;
765}
766
Paolo Bonzinie7cce672012-05-02 13:30:54 +0200767ObjectClass *object_class_get_parent(ObjectClass *class)
768{
769 TypeImpl *type = type_get_parent(class->type);
770
771 if (!type) {
772 return NULL;
773 }
774
775 type_initialize(type);
776
777 return type->class;
778}
779
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600780typedef struct OCFData
781{
782 void (*fn)(ObjectClass *klass, void *opaque);
Anthony Liguori93c511a2011-12-22 14:11:53 -0600783 const char *implements_type;
784 bool include_abstract;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600785 void *opaque;
786} OCFData;
787
788static void object_class_foreach_tramp(gpointer key, gpointer value,
789 gpointer opaque)
790{
791 OCFData *data = opaque;
792 TypeImpl *type = value;
Anthony Liguori93c511a2011-12-22 14:11:53 -0600793 ObjectClass *k;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600794
Igor Mitsyankoac451032012-02-28 15:57:11 +0400795 type_initialize(type);
Anthony Liguori93c511a2011-12-22 14:11:53 -0600796 k = type->class;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600797
Anthony Liguori93c511a2011-12-22 14:11:53 -0600798 if (!data->include_abstract && type->abstract) {
799 return;
800 }
801
802 if (data->implements_type &&
803 !object_class_dynamic_cast(k, data->implements_type)) {
804 return;
805 }
806
807 data->fn(k, data->opaque);
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600808}
809
810void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
Anthony Liguori93c511a2011-12-22 14:11:53 -0600811 const char *implements_type, bool include_abstract,
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600812 void *opaque)
813{
Anthony Liguori93c511a2011-12-22 14:11:53 -0600814 OCFData data = { fn, implements_type, include_abstract, opaque };
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600815
Hervé Poussineauf54c19c2013-12-03 16:42:00 +0100816 enumerating_types = true;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600817 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
Hervé Poussineauf54c19c2013-12-03 16:42:00 +0100818 enumerating_types = false;
Anthony Liguori2f28d2f2011-12-03 17:10:08 -0600819}
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600820
Peter Crosthwaited714b8d2015-09-08 17:38:43 +0100821static int do_object_child_foreach(Object *obj,
822 int (*fn)(Object *child, void *opaque),
823 void *opaque, bool recurse)
Paolo Bonzini32efc532012-04-11 23:30:20 +0200824{
Pavel Fedinb604a852015-10-13 13:37:45 +0100825 GHashTableIter iter;
826 ObjectProperty *prop;
Paolo Bonzini32efc532012-04-11 23:30:20 +0200827 int ret = 0;
828
Pavel Fedinb604a852015-10-13 13:37:45 +0100829 g_hash_table_iter_init(&iter, obj->properties);
830 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Paolo Bonzini32efc532012-04-11 23:30:20 +0200831 if (object_property_is_child(prop)) {
Peter Crosthwaited714b8d2015-09-08 17:38:43 +0100832 Object *child = prop->opaque;
833
834 ret = fn(child, opaque);
Paolo Bonzini32efc532012-04-11 23:30:20 +0200835 if (ret != 0) {
836 break;
837 }
Peter Crosthwaited714b8d2015-09-08 17:38:43 +0100838 if (recurse) {
839 do_object_child_foreach(child, fn, opaque, true);
840 }
Paolo Bonzini32efc532012-04-11 23:30:20 +0200841 }
842 }
843 return ret;
844}
845
Peter Crosthwaited714b8d2015-09-08 17:38:43 +0100846int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
847 void *opaque)
848{
849 return do_object_child_foreach(obj, fn, opaque, false);
850}
851
852int object_child_foreach_recursive(Object *obj,
853 int (*fn)(Object *child, void *opaque),
854 void *opaque)
855{
856 return do_object_child_foreach(obj, fn, opaque, true);
857}
858
Andreas Färber418ba9e2012-02-25 23:07:34 +0100859static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
860{
861 GSList **list = opaque;
862
863 *list = g_slist_prepend(*list, klass);
864}
865
866GSList *object_class_get_list(const char *implements_type,
867 bool include_abstract)
868{
869 GSList *list = NULL;
870
871 object_class_foreach(object_class_get_list_tramp,
872 implements_type, include_abstract, &list);
873 return list;
874}
875
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600876void object_ref(Object *obj)
877{
Peter Crosthwaite8ffad852014-06-05 23:13:36 -0700878 if (!obj) {
879 return;
880 }
Andreas Färber8438a132015-11-16 17:49:20 +0100881 atomic_inc(&obj->ref);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600882}
883
884void object_unref(Object *obj)
885{
Peter Crosthwaite8ffad852014-06-05 23:13:36 -0700886 if (!obj) {
887 return;
888 }
Andreas Färber8438a132015-11-16 17:49:20 +0100889 g_assert_cmpint(obj->ref, >, 0);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600890
891 /* parent always holds a reference to its children */
Jan Kiszkaf08c03f2013-07-02 11:36:39 +0200892 if (atomic_fetch_dec(&obj->ref) == 1) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600893 object_finalize(obj);
894 }
895}
896
Paolo Bonzini64607d02014-06-05 13:11:51 +0200897ObjectProperty *
898object_property_add(Object *obj, const char *name, const char *type,
899 ObjectPropertyAccessor *get,
900 ObjectPropertyAccessor *set,
901 ObjectPropertyRelease *release,
902 void *opaque, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600903{
Peter Maydell54852b02013-03-25 13:15:13 +0000904 ObjectProperty *prop;
Peter Crosthwaite33965902014-08-19 23:55:52 -0700905 size_t name_len = strlen(name);
906
907 if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
908 int i;
909 ObjectProperty *ret;
910 char *name_no_array = g_strdup(name);
911
912 name_no_array[name_len - 3] = '\0';
913 for (i = 0; ; ++i) {
914 char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
915
916 ret = object_property_add(obj, full_name, type, get, set,
917 release, opaque, NULL);
918 g_free(full_name);
919 if (ret) {
920 break;
921 }
922 }
923 g_free(name_no_array);
924 return ret;
925 }
Peter Maydell54852b02013-03-25 13:15:13 +0000926
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100927 if (object_property_find(obj, name, NULL) != NULL) {
Pavel Fedinb604a852015-10-13 13:37:45 +0100928 error_setg(errp, "attempt to add duplicate property '%s'"
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100929 " to object (type '%s')", name,
930 object_get_typename(obj));
Pavel Fedinb604a852015-10-13 13:37:45 +0100931 return NULL;
Peter Maydell54852b02013-03-25 13:15:13 +0000932 }
933
934 prop = g_malloc0(sizeof(*prop));
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600935
936 prop->name = g_strdup(name);
937 prop->type = g_strdup(type);
938
939 prop->get = get;
940 prop->set = set;
941 prop->release = release;
942 prop->opaque = opaque;
943
Pavel Fedinb604a852015-10-13 13:37:45 +0100944 g_hash_table_insert(obj->properties, prop->name, prop);
Paolo Bonzini64607d02014-06-05 13:11:51 +0200945 return prop;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600946}
947
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100948ObjectProperty *
949object_class_property_add(ObjectClass *klass,
950 const char *name,
951 const char *type,
952 ObjectPropertyAccessor *get,
953 ObjectPropertyAccessor *set,
954 ObjectPropertyRelease *release,
955 void *opaque,
956 Error **errp)
957{
958 ObjectProperty *prop;
959
960 if (object_class_property_find(klass, name, NULL) != NULL) {
961 error_setg(errp, "attempt to add duplicate property '%s'"
962 " to object (type '%s')", name,
963 object_class_get_name(klass));
964 return NULL;
965 }
966
967 prop = g_malloc0(sizeof(*prop));
968
969 prop->name = g_strdup(name);
970 prop->type = g_strdup(type);
971
972 prop->get = get;
973 prop->set = set;
974 prop->release = release;
975 prop->opaque = opaque;
976
977 g_hash_table_insert(klass->properties, g_strdup(name), prop);
978
979 return prop;
980}
981
Paolo Bonzini89bfe002012-04-12 18:00:18 +0200982ObjectProperty *object_property_find(Object *obj, const char *name,
983 Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600984{
985 ObjectProperty *prop;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +0100986 ObjectClass *klass = object_get_class(obj);
987
988 prop = object_class_property_find(klass, name, NULL);
989 if (prop) {
990 return prop;
991 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600992
Pavel Fedinb604a852015-10-13 13:37:45 +0100993 prop = g_hash_table_lookup(obj->properties, name);
994 if (prop) {
995 return prop;
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600996 }
997
Cole Robinsonf231b882014-03-21 19:42:26 -0400998 error_setg(errp, "Property '.%s' not found", name);
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600999 return NULL;
1000}
1001
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001002ObjectPropertyIterator *object_property_iter_init(Object *obj)
1003{
1004 ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1);
Pavel Fedinb604a852015-10-13 13:37:45 +01001005 g_hash_table_iter_init(&ret->iter, obj->properties);
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001006 ret->nextclass = object_get_class(obj);
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001007 return ret;
1008}
1009
1010void object_property_iter_free(ObjectPropertyIterator *iter)
1011{
1012 if (!iter) {
1013 return;
1014 }
1015 g_free(iter);
1016}
1017
1018ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1019{
Pavel Fedinb604a852015-10-13 13:37:45 +01001020 gpointer key, val;
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001021 while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
1022 if (!iter->nextclass) {
1023 return NULL;
1024 }
1025 g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
1026 iter->nextclass = object_class_get_parent(iter->nextclass);
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001027 }
Pavel Fedinb604a852015-10-13 13:37:45 +01001028 return val;
Daniel P. Berrangea00c9482015-10-13 13:37:40 +01001029}
1030
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001031ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
1032 Error **errp)
1033{
1034 ObjectProperty *prop;
1035 ObjectClass *parent_klass;
1036
1037 parent_klass = object_class_get_parent(klass);
1038 if (parent_klass) {
1039 prop = object_class_property_find(parent_klass, name, NULL);
1040 if (prop) {
1041 return prop;
1042 }
1043 }
1044
1045 prop = g_hash_table_lookup(klass->properties, name);
1046 if (!prop) {
1047 error_setg(errp, "Property '.%s' not found", name);
1048 }
1049 return prop;
1050}
1051
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001052void object_property_del(Object *obj, const char *name, Error **errp)
1053{
Pavel Fedinb604a852015-10-13 13:37:45 +01001054 ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1055
1056 if (!prop) {
1057 error_setg(errp, "Property '.%s' not found", name);
Anthony Liguori0866aca2011-12-23 15:34:39 -06001058 return;
1059 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001060
Anthony Liguori0866aca2011-12-23 15:34:39 -06001061 if (prop->release) {
1062 prop->release(obj, name, prop->opaque);
1063 }
Pavel Fedinb604a852015-10-13 13:37:45 +01001064 g_hash_table_remove(obj->properties, name);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001065}
1066
1067void object_property_get(Object *obj, Visitor *v, const char *name,
1068 Error **errp)
1069{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001070 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001071 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001072 return;
1073 }
1074
1075 if (!prop->get) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001076 error_setg(errp, QERR_PERMISSION_DENIED);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001077 } else {
1078 prop->get(obj, v, prop->opaque, name, errp);
1079 }
1080}
1081
1082void object_property_set(Object *obj, Visitor *v, const char *name,
1083 Error **errp)
1084{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001085 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001086 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001087 return;
1088 }
1089
1090 if (!prop->set) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001091 error_setg(errp, QERR_PERMISSION_DENIED);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001092 } else {
1093 prop->set(obj, v, prop->opaque, name, errp);
1094 }
1095}
1096
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001097void object_property_set_str(Object *obj, const char *value,
1098 const char *name, Error **errp)
1099{
1100 QString *qstr = qstring_from_str(value);
1101 object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
1102
1103 QDECREF(qstr);
1104}
1105
1106char *object_property_get_str(Object *obj, const char *name,
1107 Error **errp)
1108{
1109 QObject *ret = object_property_get_qobject(obj, name, errp);
1110 QString *qstring;
1111 char *retval;
1112
1113 if (!ret) {
1114 return NULL;
1115 }
1116 qstring = qobject_to_qstring(ret);
1117 if (!qstring) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001118 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001119 retval = NULL;
1120 } else {
1121 retval = g_strdup(qstring_get_str(qstring));
1122 }
1123
1124 QDECREF(qstring);
1125 return retval;
1126}
1127
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001128void object_property_set_link(Object *obj, Object *value,
1129 const char *name, Error **errp)
1130{
Peter Crosthwaited3c49312014-09-25 22:19:19 -07001131 if (value) {
1132 gchar *path = object_get_canonical_path(value);
1133 object_property_set_str(obj, path, name, errp);
1134 g_free(path);
1135 } else {
1136 object_property_set_str(obj, "", name, errp);
1137 }
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001138}
1139
1140Object *object_property_get_link(Object *obj, const char *name,
1141 Error **errp)
1142{
1143 char *str = object_property_get_str(obj, name, errp);
1144 Object *target = NULL;
1145
1146 if (str && *str) {
1147 target = object_resolve_path(str, NULL);
1148 if (!target) {
Markus Armbruster75158eb2015-03-16 08:57:47 +01001149 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1150 "Device '%s' not found", str);
Paolo Bonzini1d9c5a12012-02-02 10:51:57 +01001151 }
1152 }
1153
1154 g_free(str);
1155 return target;
1156}
1157
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001158void object_property_set_bool(Object *obj, bool value,
1159 const char *name, Error **errp)
1160{
Eric Blakefc48ffc2015-05-15 16:24:59 -06001161 QBool *qbool = qbool_from_bool(value);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001162 object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
1163
1164 QDECREF(qbool);
1165}
1166
1167bool object_property_get_bool(Object *obj, const char *name,
1168 Error **errp)
1169{
1170 QObject *ret = object_property_get_qobject(obj, name, errp);
1171 QBool *qbool;
1172 bool retval;
1173
1174 if (!ret) {
1175 return false;
1176 }
1177 qbool = qobject_to_qbool(ret);
1178 if (!qbool) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001179 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001180 retval = false;
1181 } else {
Eric Blakefc48ffc2015-05-15 16:24:59 -06001182 retval = qbool_get_bool(qbool);
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001183 }
1184
1185 QDECREF(qbool);
1186 return retval;
1187}
1188
1189void object_property_set_int(Object *obj, int64_t value,
1190 const char *name, Error **errp)
1191{
1192 QInt *qint = qint_from_int(value);
1193 object_property_set_qobject(obj, QOBJECT(qint), name, errp);
1194
1195 QDECREF(qint);
1196}
1197
1198int64_t object_property_get_int(Object *obj, const char *name,
1199 Error **errp)
1200{
1201 QObject *ret = object_property_get_qobject(obj, name, errp);
1202 QInt *qint;
1203 int64_t retval;
1204
1205 if (!ret) {
1206 return -1;
1207 }
1208 qint = qobject_to_qint(ret);
1209 if (!qint) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001210 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001211 retval = -1;
1212 } else {
1213 retval = qint_get_int(qint);
1214 }
1215
1216 QDECREF(qint);
1217 return retval;
1218}
1219
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001220typedef struct EnumProperty {
1221 const char * const *strings;
1222 int (*get)(Object *, Error **);
1223 void (*set)(Object *, int, Error **);
1224} EnumProperty;
1225
Hu Tao1f217722014-05-14 17:43:33 +08001226int object_property_get_enum(Object *obj, const char *name,
Daniel P. Berrangea3590da2015-05-27 16:07:56 +01001227 const char *typename, Error **errp)
Hu Tao1f217722014-05-14 17:43:33 +08001228{
Markus Armbruster4715d422015-08-25 20:00:45 +02001229 Error *err = NULL;
Hu Tao1f217722014-05-14 17:43:33 +08001230 StringOutputVisitor *sov;
1231 StringInputVisitor *siv;
Chen Fan976620a2014-08-18 14:46:34 +08001232 char *str;
Hu Tao1f217722014-05-14 17:43:33 +08001233 int ret;
Daniel P. Berrangea3590da2015-05-27 16:07:56 +01001234 ObjectProperty *prop = object_property_find(obj, name, errp);
1235 EnumProperty *enumprop;
1236
1237 if (prop == NULL) {
1238 return 0;
1239 }
1240
1241 if (!g_str_equal(prop->type, typename)) {
1242 error_setg(errp, "Property %s on %s is not '%s' enum type",
1243 name, object_class_get_name(
1244 object_get_class(obj)), typename);
1245 return 0;
1246 }
1247
1248 enumprop = prop->opaque;
Hu Tao1f217722014-05-14 17:43:33 +08001249
1250 sov = string_output_visitor_new(false);
Markus Armbruster4715d422015-08-25 20:00:45 +02001251 object_property_get(obj, string_output_get_visitor(sov), name, &err);
1252 if (err) {
1253 error_propagate(errp, err);
1254 string_output_visitor_cleanup(sov);
1255 return 0;
1256 }
Chen Fan976620a2014-08-18 14:46:34 +08001257 str = string_output_get_string(sov);
1258 siv = string_input_visitor_new(str);
Hu Tao1f217722014-05-14 17:43:33 +08001259 string_output_visitor_cleanup(sov);
1260 visit_type_enum(string_input_get_visitor(siv),
Daniel P. Berrangea3590da2015-05-27 16:07:56 +01001261 &ret, enumprop->strings, NULL, name, errp);
Chen Fan976620a2014-08-18 14:46:34 +08001262
1263 g_free(str);
Hu Tao1f217722014-05-14 17:43:33 +08001264 string_input_visitor_cleanup(siv);
1265
1266 return ret;
1267}
1268
1269void object_property_get_uint16List(Object *obj, const char *name,
1270 uint16List **list, Error **errp)
1271{
Markus Armbruster4715d422015-08-25 20:00:45 +02001272 Error *err = NULL;
Hu Tao1f217722014-05-14 17:43:33 +08001273 StringOutputVisitor *ov;
1274 StringInputVisitor *iv;
Chen Fan976620a2014-08-18 14:46:34 +08001275 char *str;
Hu Tao1f217722014-05-14 17:43:33 +08001276
1277 ov = string_output_visitor_new(false);
1278 object_property_get(obj, string_output_get_visitor(ov),
Markus Armbruster4715d422015-08-25 20:00:45 +02001279 name, &err);
1280 if (err) {
1281 error_propagate(errp, err);
1282 goto out;
1283 }
Chen Fan976620a2014-08-18 14:46:34 +08001284 str = string_output_get_string(ov);
1285 iv = string_input_visitor_new(str);
Hu Tao1f217722014-05-14 17:43:33 +08001286 visit_type_uint16List(string_input_get_visitor(iv),
1287 list, NULL, errp);
Chen Fan976620a2014-08-18 14:46:34 +08001288
1289 g_free(str);
Hu Tao1f217722014-05-14 17:43:33 +08001290 string_input_visitor_cleanup(iv);
Markus Armbruster4715d422015-08-25 20:00:45 +02001291out:
1292 string_output_visitor_cleanup(ov);
Hu Tao1f217722014-05-14 17:43:33 +08001293}
1294
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001295void object_property_parse(Object *obj, const char *string,
1296 const char *name, Error **errp)
1297{
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001298 StringInputVisitor *siv;
1299 siv = string_input_visitor_new(string);
1300 object_property_set(obj, string_input_get_visitor(siv), name, errp);
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001301
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001302 string_input_visitor_cleanup(siv);
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001303}
1304
Paolo Bonzini0b7593e2014-02-08 11:01:50 +01001305char *object_property_print(Object *obj, const char *name, bool human,
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001306 Error **errp)
1307{
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001308 StringOutputVisitor *sov;
Gonglei3a530092014-09-27 13:13:55 +08001309 char *string = NULL;
1310 Error *local_err = NULL;
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001311
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001312 sov = string_output_visitor_new(human);
1313 object_property_get(obj, string_output_get_visitor(sov), name, &local_err);
Gonglei3a530092014-09-27 13:13:55 +08001314 if (local_err) {
1315 error_propagate(errp, local_err);
1316 goto out;
1317 }
1318
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001319 string = string_output_get_string(sov);
Gonglei3a530092014-09-27 13:13:55 +08001320
1321out:
Eric Blakef8b7f1a2015-09-29 16:21:09 -06001322 string_output_visitor_cleanup(sov);
Paolo Bonzinib2cd7de2012-02-09 09:52:59 +01001323 return string;
1324}
1325
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001326const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1327{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001328 ObjectProperty *prop = object_property_find(obj, name, errp);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001329 if (prop == NULL) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001330 return NULL;
1331 }
1332
1333 return prop->type;
1334}
1335
1336Object *object_get_root(void)
1337{
Anthony Liguori8b45d442011-12-23 09:08:05 -06001338 static Object *root;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001339
Anthony Liguori8b45d442011-12-23 09:08:05 -06001340 if (!root) {
1341 root = object_new("container");
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001342 }
1343
Anthony Liguori8b45d442011-12-23 09:08:05 -06001344 return root;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001345}
1346
Daniel P. Berrangebc2256c2015-05-13 17:14:05 +01001347Object *object_get_objects_root(void)
1348{
1349 return container_get(object_get_root(), "/objects");
1350}
1351
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001352static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
1353 const char *name, Error **errp)
1354{
1355 Object *child = opaque;
1356 gchar *path;
1357
1358 path = object_get_canonical_path(child);
1359 visit_type_str(v, &path, name, errp);
1360 g_free(path);
1361}
1362
Paolo Bonzini64607d02014-06-05 13:11:51 +02001363static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
1364{
1365 return opaque;
1366}
1367
Anthony Liguoridb85b572011-12-23 08:47:39 -06001368static void object_finalize_child_property(Object *obj, const char *name,
1369 void *opaque)
1370{
1371 Object *child = opaque;
1372
Paolo Bonzinibffc6872014-06-11 11:57:38 +02001373 if (child->class->unparent) {
1374 (child->class->unparent)(child);
1375 }
1376 child->parent = NULL;
Anthony Liguoridb85b572011-12-23 08:47:39 -06001377 object_unref(child);
1378}
1379
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001380void object_property_add_child(Object *obj, const char *name,
1381 Object *child, Error **errp)
1382{
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001383 Error *local_err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001384 gchar *type;
Paolo Bonzini64607d02014-06-05 13:11:51 +02001385 ObjectProperty *op;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001386
Peter Crosthwaite8faa2f82014-09-25 22:19:52 -07001387 if (child->parent != NULL) {
1388 error_setg(errp, "child object is already parented");
1389 return;
1390 }
1391
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001392 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
1393
Paolo Bonzini64607d02014-06-05 13:11:51 +02001394 op = object_property_add(obj, name, type, object_get_child_property, NULL,
1395 object_finalize_child_property, child, &local_err);
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001396 if (local_err) {
1397 error_propagate(errp, local_err);
1398 goto out;
1399 }
Paolo Bonzini64607d02014-06-05 13:11:51 +02001400
1401 op->resolve = object_resolve_child_property;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001402 object_ref(child);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001403 child->parent = obj;
1404
Paolo Bonzinib0ed5e92013-12-20 23:21:08 +01001405out:
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001406 g_free(type);
1407}
1408
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001409void object_property_allow_set_link(Object *obj, const char *name,
1410 Object *val, Error **errp)
1411{
1412 /* Allow the link to be set, always */
1413}
1414
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001415typedef struct {
1416 Object **child;
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001417 void (*check)(Object *, const char *, Object *, Error **);
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001418 ObjectPropertyLinkFlags flags;
1419} LinkProperty;
1420
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001421static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
1422 const char *name, Error **errp)
1423{
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001424 LinkProperty *lprop = opaque;
1425 Object **child = lprop->child;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001426 gchar *path;
1427
1428 if (*child) {
1429 path = object_get_canonical_path(*child);
1430 visit_type_str(v, &path, name, errp);
1431 g_free(path);
1432 } else {
1433 path = (gchar *)"";
1434 visit_type_str(v, &path, name, errp);
1435 }
1436}
1437
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001438/*
1439 * object_resolve_link:
1440 *
1441 * Lookup an object and ensure its type matches the link property type. This
1442 * is similar to object_resolve_path() except type verification against the
1443 * link property is performed.
1444 *
1445 * Returns: The matched object or NULL on path lookup failures.
1446 */
1447static Object *object_resolve_link(Object *obj, const char *name,
1448 const char *path, Error **errp)
1449{
1450 const char *type;
1451 gchar *target_type;
1452 bool ambiguous = false;
1453 Object *target;
1454
1455 /* Go from link<FOO> to FOO. */
1456 type = object_property_get_type(obj, name, NULL);
1457 target_type = g_strndup(&type[5], strlen(type) - 6);
1458 target = object_resolve_path_type(path, target_type, &ambiguous);
1459
1460 if (ambiguous) {
Eric Blake455b0fd2015-11-10 23:51:20 -07001461 error_setg(errp, "Path '%s' does not uniquely identify an object",
1462 path);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001463 } else if (!target) {
1464 target = object_resolve_path(path, &ambiguous);
1465 if (target || ambiguous) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001466 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001467 } else {
Markus Armbruster75158eb2015-03-16 08:57:47 +01001468 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1469 "Device '%s' not found", path);
Stefan Hajnoczif5ec6702014-03-19 08:58:53 +01001470 }
1471 target = NULL;
1472 }
1473 g_free(target_type);
1474
1475 return target;
1476}
1477
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001478static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
1479 const char *name, Error **errp)
1480{
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001481 Error *local_err = NULL;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001482 LinkProperty *prop = opaque;
1483 Object **child = prop->child;
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001484 Object *old_target = *child;
1485 Object *new_target = NULL;
1486 char *path = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001487
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001488 visit_type_str(v, &path, name, &local_err);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001489
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001490 if (!local_err && strcmp(path, "") != 0) {
1491 new_target = object_resolve_link(obj, name, path, &local_err);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001492 }
1493
1494 g_free(path);
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001495 if (local_err) {
1496 error_propagate(errp, local_err);
1497 return;
1498 }
Alexander Barabashf0cdc962012-02-22 19:22:26 +02001499
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001500 prop->check(obj, name, new_target, &local_err);
1501 if (local_err) {
1502 error_propagate(errp, local_err);
1503 return;
1504 }
1505
Peter Crosthwaite8ffad852014-06-05 23:13:36 -07001506 object_ref(new_target);
Stefan Hajnoczic6aed982014-03-19 08:58:54 +01001507 *child = new_target;
Peter Crosthwaite8ffad852014-06-05 23:13:36 -07001508 object_unref(old_target);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001509}
1510
Paolo Bonzini64607d02014-06-05 13:11:51 +02001511static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
1512{
1513 LinkProperty *lprop = opaque;
1514
1515 return *lprop->child;
1516}
1517
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001518static void object_release_link_property(Object *obj, const char *name,
1519 void *opaque)
1520{
1521 LinkProperty *prop = opaque;
1522
1523 if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) {
1524 object_unref(*prop->child);
1525 }
1526 g_free(prop);
1527}
1528
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001529void object_property_add_link(Object *obj, const char *name,
1530 const char *type, Object **child,
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001531 void (*check)(Object *, const char *,
1532 Object *, Error **),
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001533 ObjectPropertyLinkFlags flags,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001534 Error **errp)
1535{
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001536 Error *local_err = NULL;
1537 LinkProperty *prop = g_malloc(sizeof(*prop));
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001538 gchar *full_type;
Paolo Bonzini64607d02014-06-05 13:11:51 +02001539 ObjectProperty *op;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001540
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001541 prop->child = child;
Stefan Hajnoczi39f72ef2014-03-19 08:58:56 +01001542 prop->check = check;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001543 prop->flags = flags;
1544
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001545 full_type = g_strdup_printf("link<%s>", type);
1546
Paolo Bonzini64607d02014-06-05 13:11:51 +02001547 op = object_property_add(obj, name, full_type,
1548 object_get_link_property,
1549 check ? object_set_link_property : NULL,
1550 object_release_link_property,
1551 prop,
1552 &local_err);
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001553 if (local_err) {
1554 error_propagate(errp, local_err);
1555 g_free(prop);
Paolo Bonzini64607d02014-06-05 13:11:51 +02001556 goto out;
Stefan Hajnoczi9561fda2014-03-19 08:58:55 +01001557 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001558
Paolo Bonzini64607d02014-06-05 13:11:51 +02001559 op->resolve = object_resolve_link_property;
1560
1561out:
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001562 g_free(full_type);
1563}
1564
Paolo Bonzinifb9e7e32015-05-05 18:29:00 +02001565void object_property_add_const_link(Object *obj, const char *name,
1566 Object *target, Error **errp)
1567{
1568 char *link_type;
1569 ObjectProperty *op;
1570
1571 link_type = g_strdup_printf("link<%s>", object_get_typename(target));
1572 op = object_property_add(obj, name, link_type,
1573 object_get_child_property, NULL,
1574 NULL, target, errp);
1575 if (op != NULL) {
1576 op->resolve = object_resolve_child_property;
1577 }
1578 g_free(link_type);
1579}
1580
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001581gchar *object_get_canonical_path_component(Object *obj)
1582{
1583 ObjectProperty *prop = NULL;
Pavel Fedinb604a852015-10-13 13:37:45 +01001584 GHashTableIter iter;
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001585
1586 g_assert(obj);
1587 g_assert(obj->parent != NULL);
1588
Pavel Fedinb604a852015-10-13 13:37:45 +01001589 g_hash_table_iter_init(&iter, obj->parent->properties);
1590 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001591 if (!object_property_is_child(prop)) {
1592 continue;
1593 }
1594
1595 if (prop->opaque == obj) {
1596 return g_strdup(prop->name);
1597 }
1598 }
1599
1600 /* obj had a parent but was not a child, should never happen */
1601 g_assert_not_reached();
1602 return NULL;
1603}
1604
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001605gchar *object_get_canonical_path(Object *obj)
1606{
1607 Object *root = object_get_root();
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001608 char *newpath, *path = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001609
1610 while (obj != root) {
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001611 char *component = object_get_canonical_path_component(obj);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001612
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001613 if (path) {
1614 newpath = g_strdup_printf("%s/%s", component, path);
1615 g_free(component);
1616 g_free(path);
1617 path = newpath;
1618 } else {
1619 path = component;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001620 }
1621
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001622 obj = obj->parent;
1623 }
1624
Stefan Hajnoczi11f590b2014-03-03 11:30:02 +01001625 newpath = g_strdup_printf("/%s", path ? path : "");
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001626 g_free(path);
1627
1628 return newpath;
1629}
1630
Andreas Färber3e84b482013-01-15 02:55:10 +01001631Object *object_resolve_path_component(Object *parent, const gchar *part)
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001632{
Paolo Bonzini89bfe002012-04-12 18:00:18 +02001633 ObjectProperty *prop = object_property_find(parent, part, NULL);
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001634 if (prop == NULL) {
1635 return NULL;
1636 }
1637
Paolo Bonzini64607d02014-06-05 13:11:51 +02001638 if (prop->resolve) {
1639 return prop->resolve(parent, prop->opaque, part);
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001640 } else {
1641 return NULL;
1642 }
1643}
1644
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001645static Object *object_resolve_abs_path(Object *parent,
1646 gchar **parts,
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001647 const char *typename,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001648 int index)
1649{
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001650 Object *child;
1651
1652 if (parts[index] == NULL) {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001653 return object_dynamic_cast(parent, typename);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001654 }
1655
1656 if (strcmp(parts[index], "") == 0) {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001657 return object_resolve_abs_path(parent, parts, typename, index + 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001658 }
1659
Paolo Bonzinia612b2a2012-03-27 18:38:45 +02001660 child = object_resolve_path_component(parent, parts[index]);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001661 if (!child) {
1662 return NULL;
1663 }
1664
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001665 return object_resolve_abs_path(child, parts, typename, index + 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001666}
1667
1668static Object *object_resolve_partial_path(Object *parent,
1669 gchar **parts,
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001670 const char *typename,
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001671 bool *ambiguous)
1672{
1673 Object *obj;
Pavel Fedinb604a852015-10-13 13:37:45 +01001674 GHashTableIter iter;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001675 ObjectProperty *prop;
1676
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001677 obj = object_resolve_abs_path(parent, parts, typename, 0);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001678
Pavel Fedinb604a852015-10-13 13:37:45 +01001679 g_hash_table_iter_init(&iter, parent->properties);
1680 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001681 Object *found;
1682
Andreas Färber5d9d3f42012-05-27 00:32:40 +02001683 if (!object_property_is_child(prop)) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001684 continue;
1685 }
1686
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001687 found = object_resolve_partial_path(prop->opaque, parts,
1688 typename, ambiguous);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001689 if (found) {
1690 if (obj) {
1691 if (ambiguous) {
1692 *ambiguous = true;
1693 }
1694 return NULL;
1695 }
1696 obj = found;
1697 }
1698
1699 if (ambiguous && *ambiguous) {
1700 return NULL;
1701 }
1702 }
1703
1704 return obj;
1705}
1706
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001707Object *object_resolve_path_type(const char *path, const char *typename,
1708 bool *ambiguous)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001709{
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001710 Object *obj;
1711 gchar **parts;
1712
1713 parts = g_strsplit(path, "/", 0);
Paolo Bonzini2e1103f2013-04-18 18:44:02 +02001714 assert(parts);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001715
Paolo Bonzini2e1103f2013-04-18 18:44:02 +02001716 if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001717 if (ambiguous) {
1718 *ambiguous = false;
1719 }
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001720 obj = object_resolve_partial_path(object_get_root(), parts,
1721 typename, ambiguous);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001722 } else {
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001723 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001724 }
1725
1726 g_strfreev(parts);
1727
1728 return obj;
1729}
1730
Paolo Bonzini02fe2db2012-02-03 11:21:01 +01001731Object *object_resolve_path(const char *path, bool *ambiguous)
1732{
1733 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1734}
1735
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001736typedef struct StringProperty
1737{
1738 char *(*get)(Object *, Error **);
1739 void (*set)(Object *, const char *, Error **);
1740} StringProperty;
1741
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001742static void property_get_str(Object *obj, Visitor *v, void *opaque,
1743 const char *name, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001744{
1745 StringProperty *prop = opaque;
1746 char *value;
Markus Armbrustere1c82372015-08-25 20:00:46 +02001747 Error *err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001748
Markus Armbrustere1c82372015-08-25 20:00:46 +02001749 value = prop->get(obj, &err);
1750 if (err) {
1751 error_propagate(errp, err);
1752 return;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001753 }
Markus Armbrustere1c82372015-08-25 20:00:46 +02001754
1755 visit_type_str(v, &value, name, errp);
1756 g_free(value);
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001757}
1758
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001759static void property_set_str(Object *obj, Visitor *v, void *opaque,
1760 const char *name, Error **errp)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001761{
1762 StringProperty *prop = opaque;
1763 char *value;
1764 Error *local_err = NULL;
1765
1766 visit_type_str(v, &value, name, &local_err);
1767 if (local_err) {
1768 error_propagate(errp, local_err);
1769 return;
1770 }
1771
1772 prop->set(obj, value, errp);
1773 g_free(value);
1774}
1775
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001776static void property_release_str(Object *obj, const char *name,
1777 void *opaque)
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001778{
1779 StringProperty *prop = opaque;
1780 g_free(prop);
1781}
1782
1783void object_property_add_str(Object *obj, const char *name,
1784 char *(*get)(Object *, Error **),
1785 void (*set)(Object *, const char *, Error **),
1786 Error **errp)
1787{
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01001788 Error *local_err = NULL;
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001789 StringProperty *prop = g_malloc0(sizeof(*prop));
1790
1791 prop->get = get;
1792 prop->set = set;
1793
1794 object_property_add(obj, name, "string",
Paolo Bonzini7b7b7d12012-02-01 17:16:22 +01001795 get ? property_get_str : NULL,
1796 set ? property_set_str : NULL,
1797 property_release_str,
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01001798 prop, &local_err);
1799 if (local_err) {
1800 error_propagate(errp, local_err);
1801 g_free(prop);
1802 }
Anthony Liguori57c9faf2012-01-30 08:55:55 -06001803}
Paolo Bonzini745549c2012-03-31 16:45:54 +02001804
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001805void object_class_property_add_str(ObjectClass *klass, const char *name,
1806 char *(*get)(Object *, Error **),
1807 void (*set)(Object *, const char *,
1808 Error **),
1809 Error **errp)
1810{
1811 Error *local_err = NULL;
1812 StringProperty *prop = g_malloc0(sizeof(*prop));
1813
1814 prop->get = get;
1815 prop->set = set;
1816
1817 object_class_property_add(klass, name, "string",
1818 get ? property_get_str : NULL,
1819 set ? property_set_str : NULL,
1820 property_release_str,
1821 prop, &local_err);
1822 if (local_err) {
1823 error_propagate(errp, local_err);
1824 g_free(prop);
1825 }
1826}
1827
Anthony Liguori0e558842012-06-25 10:32:46 -05001828typedef struct BoolProperty
1829{
1830 bool (*get)(Object *, Error **);
1831 void (*set)(Object *, bool, Error **);
1832} BoolProperty;
1833
1834static void property_get_bool(Object *obj, Visitor *v, void *opaque,
1835 const char *name, Error **errp)
1836{
1837 BoolProperty *prop = opaque;
1838 bool value;
Markus Armbruster4715d422015-08-25 20:00:45 +02001839 Error *err = NULL;
Anthony Liguori0e558842012-06-25 10:32:46 -05001840
Markus Armbruster4715d422015-08-25 20:00:45 +02001841 value = prop->get(obj, &err);
1842 if (err) {
1843 error_propagate(errp, err);
1844 return;
1845 }
1846
Anthony Liguori0e558842012-06-25 10:32:46 -05001847 visit_type_bool(v, &value, name, errp);
1848}
1849
1850static void property_set_bool(Object *obj, Visitor *v, void *opaque,
1851 const char *name, Error **errp)
1852{
1853 BoolProperty *prop = opaque;
1854 bool value;
1855 Error *local_err = NULL;
1856
1857 visit_type_bool(v, &value, name, &local_err);
1858 if (local_err) {
1859 error_propagate(errp, local_err);
1860 return;
1861 }
1862
1863 prop->set(obj, value, errp);
1864}
1865
1866static void property_release_bool(Object *obj, const char *name,
1867 void *opaque)
1868{
1869 BoolProperty *prop = opaque;
1870 g_free(prop);
1871}
1872
1873void object_property_add_bool(Object *obj, const char *name,
1874 bool (*get)(Object *, Error **),
1875 void (*set)(Object *, bool, Error **),
1876 Error **errp)
1877{
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01001878 Error *local_err = NULL;
Anthony Liguori0e558842012-06-25 10:32:46 -05001879 BoolProperty *prop = g_malloc0(sizeof(*prop));
1880
1881 prop->get = get;
1882 prop->set = set;
1883
1884 object_property_add(obj, name, "bool",
1885 get ? property_get_bool : NULL,
1886 set ? property_set_bool : NULL,
1887 property_release_bool,
Stefan Hajnoczia01aedc2014-03-04 15:28:18 +01001888 prop, &local_err);
1889 if (local_err) {
1890 error_propagate(errp, local_err);
1891 g_free(prop);
1892 }
Anthony Liguori0e558842012-06-25 10:32:46 -05001893}
1894
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001895void object_class_property_add_bool(ObjectClass *klass, const char *name,
1896 bool (*get)(Object *, Error **),
1897 void (*set)(Object *, bool, Error **),
1898 Error **errp)
1899{
1900 Error *local_err = NULL;
1901 BoolProperty *prop = g_malloc0(sizeof(*prop));
1902
1903 prop->get = get;
1904 prop->set = set;
1905
1906 object_class_property_add(klass, name, "bool",
1907 get ? property_get_bool : NULL,
1908 set ? property_set_bool : NULL,
1909 property_release_bool,
1910 prop, &local_err);
1911 if (local_err) {
1912 error_propagate(errp, local_err);
1913 g_free(prop);
1914 }
1915}
1916
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001917static void property_get_enum(Object *obj, Visitor *v, void *opaque,
1918 const char *name, Error **errp)
1919{
1920 EnumProperty *prop = opaque;
1921 int value;
Markus Armbruster4715d422015-08-25 20:00:45 +02001922 Error *err = NULL;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001923
Markus Armbruster4715d422015-08-25 20:00:45 +02001924 value = prop->get(obj, &err);
1925 if (err) {
1926 error_propagate(errp, err);
1927 return;
1928 }
1929
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001930 visit_type_enum(v, &value, prop->strings, NULL, name, errp);
1931}
1932
1933static void property_set_enum(Object *obj, Visitor *v, void *opaque,
1934 const char *name, Error **errp)
1935{
1936 EnumProperty *prop = opaque;
1937 int value;
Markus Armbruster4715d422015-08-25 20:00:45 +02001938 Error *err = NULL;
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001939
Markus Armbruster4715d422015-08-25 20:00:45 +02001940 visit_type_enum(v, &value, prop->strings, NULL, name, &err);
1941 if (err) {
1942 error_propagate(errp, err);
1943 return;
1944 }
Daniel P. Berrangea8e3fbe2015-05-13 17:14:08 +01001945 prop->set(obj, value, errp);
1946}
1947
1948static void property_release_enum(Object *obj, const char *name,
1949 void *opaque)
1950{
1951 EnumProperty *prop = opaque;
1952 g_free(prop);
1953}
1954
1955void object_property_add_enum(Object *obj, const char *name,
1956 const char *typename,
1957 const char * const *strings,
1958 int (*get)(Object *, Error **),
1959 void (*set)(Object *, int, Error **),
1960 Error **errp)
1961{
1962 Error *local_err = NULL;
1963 EnumProperty *prop = g_malloc(sizeof(*prop));
1964
1965 prop->strings = strings;
1966 prop->get = get;
1967 prop->set = set;
1968
1969 object_property_add(obj, name, typename,
1970 get ? property_get_enum : NULL,
1971 set ? property_set_enum : NULL,
1972 property_release_enum,
1973 prop, &local_err);
1974 if (local_err) {
1975 error_propagate(errp, local_err);
1976 g_free(prop);
1977 }
1978}
1979
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01001980void object_class_property_add_enum(ObjectClass *klass, const char *name,
1981 const char *typename,
1982 const char * const *strings,
1983 int (*get)(Object *, Error **),
1984 void (*set)(Object *, int, Error **),
1985 Error **errp)
1986{
1987 Error *local_err = NULL;
1988 EnumProperty *prop = g_malloc(sizeof(*prop));
1989
1990 prop->strings = strings;
1991 prop->get = get;
1992 prop->set = set;
1993
1994 object_class_property_add(klass, name, typename,
1995 get ? property_get_enum : NULL,
1996 set ? property_set_enum : NULL,
1997 property_release_enum,
1998 prop, &local_err);
1999 if (local_err) {
2000 error_propagate(errp, local_err);
2001 g_free(prop);
2002 }
2003}
2004
David Gibson8e099d12015-02-06 14:55:45 +11002005typedef struct TMProperty {
2006 void (*get)(Object *, struct tm *, Error **);
2007} TMProperty;
2008
2009static void property_get_tm(Object *obj, Visitor *v, void *opaque,
2010 const char *name, Error **errp)
2011{
2012 TMProperty *prop = opaque;
2013 Error *err = NULL;
2014 struct tm value;
2015
2016 prop->get(obj, &value, &err);
2017 if (err) {
2018 goto out;
2019 }
2020
2021 visit_start_struct(v, NULL, "struct tm", name, 0, &err);
2022 if (err) {
2023 goto out;
2024 }
2025 visit_type_int32(v, &value.tm_year, "tm_year", &err);
2026 if (err) {
2027 goto out_end;
2028 }
2029 visit_type_int32(v, &value.tm_mon, "tm_mon", &err);
2030 if (err) {
2031 goto out_end;
2032 }
2033 visit_type_int32(v, &value.tm_mday, "tm_mday", &err);
2034 if (err) {
2035 goto out_end;
2036 }
2037 visit_type_int32(v, &value.tm_hour, "tm_hour", &err);
2038 if (err) {
2039 goto out_end;
2040 }
2041 visit_type_int32(v, &value.tm_min, "tm_min", &err);
2042 if (err) {
2043 goto out_end;
2044 }
2045 visit_type_int32(v, &value.tm_sec, "tm_sec", &err);
2046 if (err) {
2047 goto out_end;
2048 }
2049out_end:
2050 error_propagate(errp, err);
2051 err = NULL;
2052 visit_end_struct(v, errp);
2053out:
2054 error_propagate(errp, err);
2055
2056}
2057
2058static void property_release_tm(Object *obj, const char *name,
2059 void *opaque)
2060{
2061 TMProperty *prop = opaque;
2062 g_free(prop);
2063}
2064
2065void object_property_add_tm(Object *obj, const char *name,
2066 void (*get)(Object *, struct tm *, Error **),
2067 Error **errp)
2068{
2069 Error *local_err = NULL;
2070 TMProperty *prop = g_malloc0(sizeof(*prop));
2071
2072 prop->get = get;
2073
2074 object_property_add(obj, name, "struct tm",
2075 get ? property_get_tm : NULL, NULL,
2076 property_release_tm,
2077 prop, &local_err);
2078 if (local_err) {
2079 error_propagate(errp, local_err);
2080 g_free(prop);
2081 }
2082}
2083
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002084void object_class_property_add_tm(ObjectClass *klass, const char *name,
2085 void (*get)(Object *, struct tm *, Error **),
2086 Error **errp)
2087{
2088 Error *local_err = NULL;
2089 TMProperty *prop = g_malloc0(sizeof(*prop));
2090
2091 prop->get = get;
2092
2093 object_class_property_add(klass, name, "struct tm",
2094 get ? property_get_tm : NULL, NULL,
2095 property_release_tm,
2096 prop, &local_err);
2097 if (local_err) {
2098 error_propagate(errp, local_err);
2099 g_free(prop);
2100 }
2101}
2102
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002103static char *qdev_get_type(Object *obj, Error **errp)
2104{
2105 return g_strdup(object_get_typename(obj));
2106}
2107
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002108static void property_get_uint8_ptr(Object *obj, Visitor *v,
2109 void *opaque, const char *name,
2110 Error **errp)
2111{
2112 uint8_t value = *(uint8_t *)opaque;
2113 visit_type_uint8(v, &value, name, errp);
2114}
2115
2116static void property_get_uint16_ptr(Object *obj, Visitor *v,
2117 void *opaque, const char *name,
2118 Error **errp)
2119{
2120 uint16_t value = *(uint16_t *)opaque;
2121 visit_type_uint16(v, &value, name, errp);
2122}
2123
2124static void property_get_uint32_ptr(Object *obj, Visitor *v,
2125 void *opaque, const char *name,
2126 Error **errp)
2127{
2128 uint32_t value = *(uint32_t *)opaque;
2129 visit_type_uint32(v, &value, name, errp);
2130}
2131
2132static void property_get_uint64_ptr(Object *obj, Visitor *v,
2133 void *opaque, const char *name,
2134 Error **errp)
2135{
2136 uint64_t value = *(uint64_t *)opaque;
2137 visit_type_uint64(v, &value, name, errp);
2138}
2139
2140void object_property_add_uint8_ptr(Object *obj, const char *name,
2141 const uint8_t *v, Error **errp)
2142{
2143 object_property_add(obj, name, "uint8", property_get_uint8_ptr,
2144 NULL, NULL, (void *)v, errp);
2145}
2146
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002147void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2148 const uint8_t *v, Error **errp)
2149{
2150 object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
2151 NULL, NULL, (void *)v, errp);
2152}
2153
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002154void object_property_add_uint16_ptr(Object *obj, const char *name,
2155 const uint16_t *v, Error **errp)
2156{
2157 object_property_add(obj, name, "uint16", property_get_uint16_ptr,
2158 NULL, NULL, (void *)v, errp);
2159}
2160
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002161void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2162 const uint16_t *v, Error **errp)
2163{
2164 object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
2165 NULL, NULL, (void *)v, errp);
2166}
2167
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002168void object_property_add_uint32_ptr(Object *obj, const char *name,
2169 const uint32_t *v, Error **errp)
2170{
2171 object_property_add(obj, name, "uint32", property_get_uint32_ptr,
2172 NULL, NULL, (void *)v, errp);
2173}
2174
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002175void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2176 const uint32_t *v, Error **errp)
2177{
2178 object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
2179 NULL, NULL, (void *)v, errp);
2180}
2181
Michael S. Tsirkine732ea62013-09-22 10:10:17 +03002182void object_property_add_uint64_ptr(Object *obj, const char *name,
2183 const uint64_t *v, Error **errp)
2184{
2185 object_property_add(obj, name, "uint64", property_get_uint64_ptr,
2186 NULL, NULL, (void *)v, errp);
2187}
2188
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002189void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2190 const uint64_t *v, Error **errp)
2191{
2192 object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
2193 NULL, NULL, (void *)v, errp);
2194}
2195
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002196typedef struct {
2197 Object *target_obj;
Eduardo Habkost1590d262015-04-09 16:57:29 -03002198 char *target_name;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002199} AliasProperty;
2200
2201static void property_get_alias(Object *obj, struct Visitor *v, void *opaque,
2202 const char *name, Error **errp)
2203{
2204 AliasProperty *prop = opaque;
2205
2206 object_property_get(prop->target_obj, v, prop->target_name, errp);
2207}
2208
2209static void property_set_alias(Object *obj, struct Visitor *v, void *opaque,
2210 const char *name, Error **errp)
2211{
2212 AliasProperty *prop = opaque;
2213
2214 object_property_set(prop->target_obj, v, prop->target_name, errp);
2215}
2216
Paolo Bonzini64607d02014-06-05 13:11:51 +02002217static Object *property_resolve_alias(Object *obj, void *opaque,
2218 const gchar *part)
2219{
2220 AliasProperty *prop = opaque;
2221
2222 return object_resolve_path_component(prop->target_obj, prop->target_name);
2223}
2224
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002225static void property_release_alias(Object *obj, const char *name, void *opaque)
2226{
2227 AliasProperty *prop = opaque;
2228
Eduardo Habkost1590d262015-04-09 16:57:29 -03002229 g_free(prop->target_name);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002230 g_free(prop);
2231}
2232
2233void object_property_add_alias(Object *obj, const char *name,
2234 Object *target_obj, const char *target_name,
2235 Error **errp)
2236{
2237 AliasProperty *prop;
Paolo Bonzini64607d02014-06-05 13:11:51 +02002238 ObjectProperty *op;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002239 ObjectProperty *target_prop;
Paolo Bonzinid1906982014-06-10 11:17:35 +02002240 gchar *prop_type;
Gonglei8ae9a9e2014-09-27 13:13:56 +08002241 Error *local_err = NULL;
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002242
2243 target_prop = object_property_find(target_obj, target_name, errp);
2244 if (!target_prop) {
2245 return;
2246 }
2247
Paolo Bonzinid1906982014-06-10 11:17:35 +02002248 if (object_property_is_child(target_prop)) {
2249 prop_type = g_strdup_printf("link%s",
2250 target_prop->type + strlen("child"));
2251 } else {
2252 prop_type = g_strdup(target_prop->type);
2253 }
2254
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002255 prop = g_malloc(sizeof(*prop));
2256 prop->target_obj = target_obj;
Eduardo Habkost1590d262015-04-09 16:57:29 -03002257 prop->target_name = g_strdup(target_name);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002258
Paolo Bonzinid1906982014-06-10 11:17:35 +02002259 op = object_property_add(obj, name, prop_type,
Paolo Bonzini64607d02014-06-05 13:11:51 +02002260 property_get_alias,
2261 property_set_alias,
2262 property_release_alias,
Gonglei8ae9a9e2014-09-27 13:13:56 +08002263 prop, &local_err);
2264 if (local_err) {
2265 error_propagate(errp, local_err);
2266 g_free(prop);
2267 goto out;
2268 }
Paolo Bonzini64607d02014-06-05 13:11:51 +02002269 op->resolve = property_resolve_alias;
Paolo Bonzinid1906982014-06-10 11:17:35 +02002270
Andreas Färbera18bb412015-03-27 17:34:10 +01002271 object_property_set_description(obj, op->name,
Gonglei80742642014-10-07 14:33:21 +08002272 target_prop->description,
2273 &error_abort);
2274
Gonglei8ae9a9e2014-09-27 13:13:56 +08002275out:
Paolo Bonzinid1906982014-06-10 11:17:35 +02002276 g_free(prop_type);
Stefan Hajnoczief7c7ff2014-06-18 17:58:28 +08002277}
2278
Gonglei80742642014-10-07 14:33:21 +08002279void object_property_set_description(Object *obj, const char *name,
2280 const char *description, Error **errp)
2281{
2282 ObjectProperty *op;
2283
2284 op = object_property_find(obj, name, errp);
2285 if (!op) {
2286 return;
2287 }
2288
2289 g_free(op->description);
2290 op->description = g_strdup(description);
2291}
2292
Daniel P. Berrange16bf7f52015-10-13 13:37:46 +01002293void object_class_property_set_description(ObjectClass *klass,
2294 const char *name,
2295 const char *description,
2296 Error **errp)
2297{
2298 ObjectProperty *op;
2299
2300 op = g_hash_table_lookup(klass->properties, name);
2301 if (!op) {
2302 error_setg(errp, "Property '.%s' not found", name);
2303 return;
2304 }
2305
2306 g_free(op->description);
2307 op->description = g_strdup(description);
2308}
2309
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002310static void object_instance_init(Object *obj)
2311{
2312 object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
2313}
2314
Paolo Bonzini745549c2012-03-31 16:45:54 +02002315static void register_types(void)
2316{
2317 static TypeInfo interface_info = {
2318 .name = TYPE_INTERFACE,
Anthony Liguori33e95c62012-08-10 13:16:10 +10002319 .class_size = sizeof(InterfaceClass),
Paolo Bonzini745549c2012-03-31 16:45:54 +02002320 .abstract = true,
2321 };
2322
2323 static TypeInfo object_info = {
2324 .name = TYPE_OBJECT,
2325 .instance_size = sizeof(Object),
Paolo Bonzini2f262e02012-04-02 17:33:51 +02002326 .instance_init = object_instance_init,
Paolo Bonzini745549c2012-03-31 16:45:54 +02002327 .abstract = true,
2328 };
2329
Paolo Bonzini049cb3c2012-04-04 15:58:40 +02002330 type_interface = type_register_internal(&interface_info);
2331 type_register_internal(&object_info);
Paolo Bonzini745549c2012-03-31 16:45:54 +02002332}
2333
2334type_init(register_types)