]> git.proxmox.com Git - mirror_qemu.git/blame - qom/object.c
vfio: spapr: Add DMA memory preregistering (SPAPR IOMMU v2)
[mirror_qemu.git] / qom / object.c
CommitLineData
2f28d2ff
AL
1/*
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
9bbc853b 13#include "qemu/osdep.h"
da34e65c 14#include "qapi/error.h"
14cccb61 15#include "qom/object.h"
a31bdae5 16#include "qom/object_interfaces.h"
f348b6d1 17#include "qemu/cutils.h"
7b1b5d19 18#include "qapi/visitor.h"
1f21772d 19#include "qapi-visit.h"
b2cd7dee
PB
20#include "qapi/string-input-visitor.h"
21#include "qapi/string-output-visitor.h"
7b1b5d19 22#include "qapi/qmp/qerror.h"
fa131d94 23#include "trace.h"
2f28d2ff 24
7b7b7d18
PB
25/* TODO: replace QObject with a simpler visitor to avoid a dependency
26 * of the QOM core on QObject? */
14cccb61 27#include "qom/qom-qobject.h"
7b1b5d19
PB
28#include "qapi/qmp/qobject.h"
29#include "qapi/qmp/qbool.h"
30#include "qapi/qmp/qint.h"
31#include "qapi/qmp/qstring.h"
7b7b7d18 32
2f28d2ff
AL
33#define MAX_INTERFACES 32
34
35typedef struct InterfaceImpl InterfaceImpl;
36typedef struct TypeImpl TypeImpl;
37
38struct InterfaceImpl
39{
33e95c63 40 const char *typename;
2f28d2ff
AL
41};
42
43struct TypeImpl
44{
45 const char *name;
46
47 size_t class_size;
48
49 size_t instance_size;
50
51 void (*class_init)(ObjectClass *klass, void *data);
3b50e311 52 void (*class_base_init)(ObjectClass *klass, void *data);
2f28d2ff
AL
53 void (*class_finalize)(ObjectClass *klass, void *data);
54
55 void *class_data;
56
57 void (*instance_init)(Object *obj);
8231c2dd 58 void (*instance_post_init)(Object *obj);
2f28d2ff
AL
59 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
9970bd88
PB
72static Type type_interface;
73
2f28d2ff
AL
74static 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
f54c19ca
HP
85static bool enumerating_types;
86
2f28d2ff
AL
87static void type_table_add(TypeImpl *ti)
88{
f54c19ca 89 assert(!enumerating_types);
2f28d2ff
AL
90 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
b061dc41 98static TypeImpl *type_new(const TypeInfo *info)
2f28d2ff
AL
99{
100 TypeImpl *ti = g_malloc0(sizeof(*ti));
33e95c63 101 int i;
2f28d2ff
AL
102
103 g_assert(info->name != NULL);
104
73093354
AL
105 if (type_table_lookup(info->name) != NULL) {
106 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
107 abort();
108 }
109
2f28d2ff
AL
110 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;
3b50e311 117 ti->class_base_init = info->class_base_init;
2f28d2ff
AL
118 ti->class_finalize = info->class_finalize;
119 ti->class_data = info->class_data;
120
121 ti->instance_init = info->instance_init;
8231c2dd 122 ti->instance_post_init = info->instance_post_init;
2f28d2ff
AL
123 ti->instance_finalize = info->instance_finalize;
124
125 ti->abstract = info->abstract;
126
33e95c63
AL
127 for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
128 ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
2f28d2ff 129 }
33e95c63 130 ti->num_interfaces = i;
2f28d2ff 131
b061dc41
PB
132 return ti;
133}
2f28d2ff 134
b061dc41
PB
135static TypeImpl *type_register_internal(const TypeInfo *info)
136{
137 TypeImpl *ti;
138 ti = type_new(info);
139
140 type_table_add(ti);
2f28d2ff
AL
141 return ti;
142}
143
049cb3cf
PB
144TypeImpl *type_register(const TypeInfo *info)
145{
146 assert(info->parent);
147 return type_register_internal(info);
148}
149
2f28d2ff
AL
150TypeImpl *type_register_static(const TypeInfo *info)
151{
152 return type_register(info);
153}
154
155static TypeImpl *type_get_by_name(const char *name)
156{
157 if (name == NULL) {
158 return NULL;
159 }
160
161 return type_table_lookup(name);
162}
163
164static TypeImpl *type_get_parent(TypeImpl *type)
165{
166 if (!type->parent_type && type->parent) {
167 type->parent_type = type_get_by_name(type->parent);
168 g_assert(type->parent_type != NULL);
169 }
170
171 return type->parent_type;
172}
173
174static bool type_has_parent(TypeImpl *type)
175{
176 return (type->parent != NULL);
177}
178
179static size_t type_class_get_size(TypeImpl *ti)
180{
181 if (ti->class_size) {
182 return ti->class_size;
183 }
184
185 if (type_has_parent(ti)) {
186 return type_class_get_size(type_get_parent(ti));
187 }
188
189 return sizeof(ObjectClass);
190}
191
aca59af6
IM
192static size_t type_object_get_size(TypeImpl *ti)
193{
194 if (ti->instance_size) {
195 return ti->instance_size;
196 }
197
198 if (type_has_parent(ti)) {
199 return type_object_get_size(type_get_parent(ti));
200 }
201
202 return 0;
203}
204
3f97b53a
BR
205size_t object_type_get_instance_size(const char *typename)
206{
207 TypeImpl *type = type_get_by_name(typename);
208
209 g_assert(type != NULL);
210 return type_object_get_size(type);
211}
212
33e95c63 213static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
2f28d2ff 214{
33e95c63
AL
215 assert(target_type);
216
b30d8054 217 /* Check if target_type is a direct ancestor of type */
33e95c63
AL
218 while (type) {
219 if (type == target_type) {
220 return true;
221 }
2f28d2ff 222
33e95c63
AL
223 type = type_get_parent(type);
224 }
225
226 return false;
227}
228
229static void type_initialize(TypeImpl *ti);
230
b061dc41
PB
231static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
232 TypeImpl *parent_type)
33e95c63
AL
233{
234 InterfaceClass *new_iface;
235 TypeInfo info = { };
236 TypeImpl *iface_impl;
237
b061dc41
PB
238 info.parent = parent_type->name;
239 info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
33e95c63
AL
240 info.abstract = true;
241
b061dc41
PB
242 iface_impl = type_new(&info);
243 iface_impl->parent_type = parent_type;
33e95c63
AL
244 type_initialize(iface_impl);
245 g_free((char *)info.name);
246
247 new_iface = (InterfaceClass *)iface_impl->class;
248 new_iface->concrete_class = ti->class;
b061dc41 249 new_iface->interface_type = interface_type;
33e95c63
AL
250
251 ti->class->interfaces = g_slist_append(ti->class->interfaces,
252 iface_impl->class);
2f28d2ff
AL
253}
254
16bf7f52
DB
255static void object_property_free(gpointer data)
256{
257 ObjectProperty *prop = data;
258
259 g_free(prop->name);
260 g_free(prop->type);
261 g_free(prop->description);
262 g_free(prop);
263}
264
ac451033 265static void type_initialize(TypeImpl *ti)
2f28d2ff 266{
745549c8 267 TypeImpl *parent;
2f28d2ff
AL
268
269 if (ti->class) {
270 return;
271 }
272
273 ti->class_size = type_class_get_size(ti);
aca59af6 274 ti->instance_size = type_object_get_size(ti);
2f28d2ff
AL
275
276 ti->class = g_malloc0(ti->class_size);
2f28d2ff 277
745549c8
PB
278 parent = type_get_parent(ti);
279 if (parent) {
ac451033 280 type_initialize(parent);
33e95c63
AL
281 GSList *e;
282 int i;
2f28d2ff 283
8438a135 284 g_assert_cmpint(parent->class_size, <=, ti->class_size);
745549c8 285 memcpy(ti->class, parent->class, parent->class_size);
3e407de4 286 ti->class->interfaces = NULL;
16bf7f52
DB
287 ti->class->properties = g_hash_table_new_full(
288 g_str_hash, g_str_equal, g_free, object_property_free);
33e95c63
AL
289
290 for (e = parent->class->interfaces; e; e = e->next) {
b061dc41
PB
291 InterfaceClass *iface = e->data;
292 ObjectClass *klass = OBJECT_CLASS(iface);
293
294 type_initialize_interface(ti, iface->interface_type, klass->type);
33e95c63
AL
295 }
296
297 for (i = 0; i < ti->num_interfaces; i++) {
298 TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
299 for (e = ti->class->interfaces; e; e = e->next) {
300 TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
301
302 if (type_is_ancestor(target_type, t)) {
303 break;
304 }
305 }
306
307 if (e) {
308 continue;
309 }
310
b061dc41 311 type_initialize_interface(ti, t, t);
33e95c63 312 }
16bf7f52
DB
313 } else {
314 ti->class->properties = g_hash_table_new_full(
315 g_str_hash, g_str_equal, g_free, object_property_free);
745549c8 316 }
2f28d2ff 317
745549c8 318 ti->class->type = ti;
3b50e311 319
745549c8
PB
320 while (parent) {
321 if (parent->class_base_init) {
322 parent->class_base_init(ti->class, ti->class_data);
3b50e311 323 }
745549c8 324 parent = type_get_parent(parent);
2f28d2ff
AL
325 }
326
2f28d2ff
AL
327 if (ti->class_init) {
328 ti->class_init(ti->class, ti->class_data);
329 }
2f28d2ff
AL
330}
331
332static void object_init_with_type(Object *obj, TypeImpl *ti)
333{
2f28d2ff
AL
334 if (type_has_parent(ti)) {
335 object_init_with_type(obj, type_get_parent(ti));
336 }
337
2f28d2ff
AL
338 if (ti->instance_init) {
339 ti->instance_init(obj);
340 }
341}
342
8231c2dd
EH
343static void object_post_init_with_type(Object *obj, TypeImpl *ti)
344{
345 if (ti->instance_post_init) {
346 ti->instance_post_init(obj);
347 }
348
349 if (type_has_parent(ti)) {
350 object_post_init_with_type(obj, type_get_parent(ti));
351 }
352}
353
5b9237f6 354void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
2f28d2ff
AL
355{
356 Object *obj = data;
357
358 g_assert(type != NULL);
ac451033 359 type_initialize(type);
aca59af6 360
8438a135 361 g_assert_cmpint(type->instance_size, >=, sizeof(Object));
2f28d2ff 362 g_assert(type->abstract == false);
8438a135 363 g_assert_cmpint(size, >=, type->instance_size);
2f28d2ff
AL
364
365 memset(obj, 0, type->instance_size);
366 obj->class = type->class;
764b6312 367 object_ref(obj);
b604a854
PF
368 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
369 NULL, object_property_free);
2f28d2ff 370 object_init_with_type(obj, type);
8231c2dd 371 object_post_init_with_type(obj, type);
2f28d2ff
AL
372}
373
213f0c4f 374void object_initialize(void *data, size_t size, const char *typename)
2f28d2ff
AL
375{
376 TypeImpl *type = type_get_by_name(typename);
377
5b9237f6 378 object_initialize_with_type(data, size, type);
2f28d2ff
AL
379}
380
5d9d3f47
AF
381static inline bool object_property_is_child(ObjectProperty *prop)
382{
383 return strstart(prop->type, "child<", NULL);
384}
385
57c9fafe
AL
386static void object_property_del_all(Object *obj)
387{
b604a854
PF
388 ObjectProperty *prop;
389 GHashTableIter iter;
390 gpointer key, value;
391 bool released;
392
393 do {
394 released = false;
395 g_hash_table_iter_init(&iter, obj->properties);
396 while (g_hash_table_iter_next(&iter, &key, &value)) {
397 prop = value;
398 if (prop->release) {
399 prop->release(obj, prop->name, prop->opaque);
400 prop->release = NULL;
401 released = true;
402 break;
403 }
404 g_hash_table_iter_remove(&iter);
57c9fafe 405 }
b604a854 406 } while (released);
57c9fafe 407
b604a854 408 g_hash_table_unref(obj->properties);
57c9fafe
AL
409}
410
411static void object_property_del_child(Object *obj, Object *child, Error **errp)
412{
413 ObjectProperty *prop;
b604a854
PF
414 GHashTableIter iter;
415 gpointer key, value;
57c9fafe 416
b604a854
PF
417 g_hash_table_iter_init(&iter, obj->properties);
418 while (g_hash_table_iter_next(&iter, &key, &value)) {
419 prop = value;
420 if (object_property_is_child(prop) && prop->opaque == child) {
421 if (prop->release) {
422 prop->release(obj, prop->name, prop->opaque);
423 prop->release = NULL;
424 }
425 break;
426 }
427 }
428 g_hash_table_iter_init(&iter, obj->properties);
429 while (g_hash_table_iter_next(&iter, &key, &value)) {
430 prop = value;
5d9d3f47 431 if (object_property_is_child(prop) && prop->opaque == child) {
b604a854 432 g_hash_table_iter_remove(&iter);
6c1fdcf9 433 break;
57c9fafe
AL
434 }
435 }
436}
437
438void object_unparent(Object *obj)
439{
e998fa8d
MT
440 if (obj->parent) {
441 object_property_del_child(obj->parent, obj, NULL);
442 }
57c9fafe
AL
443}
444
2f28d2ff
AL
445static void object_deinit(Object *obj, TypeImpl *type)
446{
447 if (type->instance_finalize) {
448 type->instance_finalize(obj);
449 }
450
2f28d2ff
AL
451 if (type_has_parent(type)) {
452 object_deinit(obj, type_get_parent(type));
453 }
454}
455
339c2708 456static void object_finalize(void *data)
2f28d2ff
AL
457{
458 Object *obj = data;
459 TypeImpl *ti = obj->class->type;
460
57c9fafe 461 object_property_del_all(obj);
76a6e1cc 462 object_deinit(obj, ti);
db85b575 463
8438a135 464 g_assert_cmpint(obj->ref, ==, 0);
fde9bf44
PB
465 if (obj->free) {
466 obj->free(obj);
467 }
2f28d2ff
AL
468}
469
470Object *object_new_with_type(Type type)
471{
472 Object *obj;
473
474 g_assert(type != NULL);
ac451033 475 type_initialize(type);
2f28d2ff
AL
476
477 obj = g_malloc(type->instance_size);
5b9237f6 478 object_initialize_with_type(obj, type->instance_size, type);
fde9bf44 479 obj->free = g_free;
2f28d2ff
AL
480
481 return obj;
482}
483
484Object *object_new(const char *typename)
485{
486 TypeImpl *ti = type_get_by_name(typename);
487
488 return object_new_with_type(ti);
489}
490
a31bdae5
DB
491
492Object *object_new_with_props(const char *typename,
493 Object *parent,
494 const char *id,
495 Error **errp,
496 ...)
497{
498 va_list vargs;
499 Object *obj;
500
501 va_start(vargs, errp);
502 obj = object_new_with_propv(typename, parent, id, errp, vargs);
503 va_end(vargs);
504
505 return obj;
506}
507
508
509Object *object_new_with_propv(const char *typename,
510 Object *parent,
511 const char *id,
512 Error **errp,
513 va_list vargs)
514{
515 Object *obj;
516 ObjectClass *klass;
517 Error *local_err = NULL;
518
519 klass = object_class_by_name(typename);
520 if (!klass) {
521 error_setg(errp, "invalid object type: %s", typename);
522 return NULL;
523 }
524
525 if (object_class_is_abstract(klass)) {
526 error_setg(errp, "object type '%s' is abstract", typename);
527 return NULL;
528 }
529 obj = object_new(typename);
530
531 if (object_set_propv(obj, &local_err, vargs) < 0) {
532 goto error;
533 }
534
535 object_property_add_child(parent, id, obj, &local_err);
536 if (local_err) {
537 goto error;
538 }
539
540 if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
541 user_creatable_complete(obj, &local_err);
542 if (local_err) {
543 object_unparent(obj);
544 goto error;
545 }
546 }
547
548 object_unref(OBJECT(obj));
549 return obj;
550
551 error:
621ff94d 552 error_propagate(errp, local_err);
a31bdae5
DB
553 object_unref(obj);
554 return NULL;
555}
556
557
558int object_set_props(Object *obj,
559 Error **errp,
560 ...)
561{
562 va_list vargs;
563 int ret;
564
565 va_start(vargs, errp);
566 ret = object_set_propv(obj, errp, vargs);
567 va_end(vargs);
568
569 return ret;
570}
571
572
573int object_set_propv(Object *obj,
574 Error **errp,
575 va_list vargs)
576{
577 const char *propname;
578 Error *local_err = NULL;
579
580 propname = va_arg(vargs, char *);
581 while (propname != NULL) {
582 const char *value = va_arg(vargs, char *);
583
584 g_assert(value != NULL);
585 object_property_parse(obj, value, propname, &local_err);
586 if (local_err) {
587 error_propagate(errp, local_err);
588 return -1;
589 }
590 propname = va_arg(vargs, char *);
591 }
592
593 return 0;
594}
595
596
2f28d2ff
AL
597Object *object_dynamic_cast(Object *obj, const char *typename)
598{
b7f43fe4 599 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
acc4af3f
PB
600 return obj;
601 }
602
2f28d2ff
AL
603 return NULL;
604}
605
be17f18b
PB
606Object *object_dynamic_cast_assert(Object *obj, const char *typename,
607 const char *file, int line, const char *func)
2f28d2ff 608{
fa131d94
PB
609 trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
610 typename, file, line, func);
611
3556c233 612#ifdef CONFIG_QOM_CAST_DEBUG
03587328
AL
613 int i;
614 Object *inst;
615
95916abc 616 for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
0ab4c94c 617 if (obj->class->object_cast_cache[i] == typename) {
03587328
AL
618 goto out;
619 }
620 }
621
622 inst = object_dynamic_cast(obj, typename);
2f28d2ff 623
b7f43fe4 624 if (!inst && obj) {
be17f18b
PB
625 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
626 file, line, func, obj, typename);
2f28d2ff
AL
627 abort();
628 }
629
3556c233 630 assert(obj == inst);
03587328 631
95916abc 632 if (obj && obj == inst) {
03587328 633 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
0ab4c94c
PC
634 obj->class->object_cast_cache[i - 1] =
635 obj->class->object_cast_cache[i];
03587328 636 }
0ab4c94c 637 obj->class->object_cast_cache[i - 1] = typename;
03587328
AL
638 }
639
640out:
3556c233
PB
641#endif
642 return obj;
2f28d2ff
AL
643}
644
645ObjectClass *object_class_dynamic_cast(ObjectClass *class,
646 const char *typename)
647{
33e95c63 648 ObjectClass *ret = NULL;
bf0fda34
PB
649 TypeImpl *target_type;
650 TypeImpl *type;
2f28d2ff 651
bf0fda34
PB
652 if (!class) {
653 return NULL;
654 }
655
793c96b5 656 /* A simple fast path that can trigger a lot for leaf classes. */
bf0fda34 657 type = class->type;
793c96b5
PB
658 if (type->name == typename) {
659 return class;
660 }
661
bf0fda34 662 target_type = type_get_by_name(typename);
9ab880b3
AG
663 if (!target_type) {
664 /* target class type unknown, so fail the cast */
665 return NULL;
666 }
667
00e2ceae
PC
668 if (type->class->interfaces &&
669 type_is_ancestor(target_type, type_interface)) {
33e95c63
AL
670 int found = 0;
671 GSList *i;
2f28d2ff 672
33e95c63
AL
673 for (i = class->interfaces; i; i = i->next) {
674 ObjectClass *target_class = i->data;
675
676 if (type_is_ancestor(target_class->type, target_type)) {
677 ret = target_class;
678 found++;
679 }
680 }
681
682 /* The match was ambiguous, don't allow a cast */
683 if (found > 1) {
684 ret = NULL;
685 }
686 } else if (type_is_ancestor(type, target_type)) {
687 ret = class;
2f28d2ff
AL
688 }
689
33e95c63 690 return ret;
2f28d2ff
AL
691}
692
693ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
be17f18b
PB
694 const char *typename,
695 const char *file, int line,
696 const char *func)
2f28d2ff 697{
fa131d94
PB
698 ObjectClass *ret;
699
700 trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
701 typename, file, line, func);
2f28d2ff 702
03587328
AL
703#ifdef CONFIG_QOM_CAST_DEBUG
704 int i;
705
9d6a3d58 706 for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
0ab4c94c 707 if (class->class_cast_cache[i] == typename) {
03587328
AL
708 ret = class;
709 goto out;
710 }
711 }
712#else
9d6a3d58 713 if (!class || !class->interfaces) {
3556c233
PB
714 return class;
715 }
716#endif
717
fa131d94 718 ret = object_class_dynamic_cast(class, typename);
bf0fda34 719 if (!ret && class) {
be17f18b
PB
720 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
721 file, line, func, class, typename);
2f28d2ff
AL
722 abort();
723 }
724
03587328 725#ifdef CONFIG_QOM_CAST_DEBUG
9d6a3d58 726 if (class && ret == class) {
03587328 727 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
0ab4c94c 728 class->class_cast_cache[i - 1] = class->class_cast_cache[i];
03587328 729 }
0ab4c94c 730 class->class_cast_cache[i - 1] = typename;
03587328
AL
731 }
732out:
733#endif
2f28d2ff
AL
734 return ret;
735}
736
737const char *object_get_typename(Object *obj)
738{
739 return obj->class->type->name;
740}
741
742ObjectClass *object_get_class(Object *obj)
743{
744 return obj->class;
745}
746
17862378
AF
747bool object_class_is_abstract(ObjectClass *klass)
748{
749 return klass->type->abstract;
750}
751
2f28d2ff
AL
752const char *object_class_get_name(ObjectClass *klass)
753{
754 return klass->type->name;
755}
756
757ObjectClass *object_class_by_name(const char *typename)
758{
759 TypeImpl *type = type_get_by_name(typename);
760
761 if (!type) {
762 return NULL;
763 }
764
ac451033 765 type_initialize(type);
2f28d2ff
AL
766
767 return type->class;
768}
769
e7cce67f
PB
770ObjectClass *object_class_get_parent(ObjectClass *class)
771{
772 TypeImpl *type = type_get_parent(class->type);
773
774 if (!type) {
775 return NULL;
776 }
777
778 type_initialize(type);
779
780 return type->class;
781}
782
2f28d2ff
AL
783typedef struct OCFData
784{
785 void (*fn)(ObjectClass *klass, void *opaque);
93c511a1
AL
786 const char *implements_type;
787 bool include_abstract;
2f28d2ff
AL
788 void *opaque;
789} OCFData;
790
791static void object_class_foreach_tramp(gpointer key, gpointer value,
792 gpointer opaque)
793{
794 OCFData *data = opaque;
795 TypeImpl *type = value;
93c511a1 796 ObjectClass *k;
2f28d2ff 797
ac451033 798 type_initialize(type);
93c511a1 799 k = type->class;
2f28d2ff 800
93c511a1
AL
801 if (!data->include_abstract && type->abstract) {
802 return;
803 }
804
805 if (data->implements_type &&
806 !object_class_dynamic_cast(k, data->implements_type)) {
807 return;
808 }
809
810 data->fn(k, data->opaque);
2f28d2ff
AL
811}
812
813void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
93c511a1 814 const char *implements_type, bool include_abstract,
2f28d2ff
AL
815 void *opaque)
816{
93c511a1 817 OCFData data = { fn, implements_type, include_abstract, opaque };
2f28d2ff 818
f54c19ca 819 enumerating_types = true;
2f28d2ff 820 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
f54c19ca 821 enumerating_types = false;
2f28d2ff 822}
57c9fafe 823
d714b8de
PC
824static int do_object_child_foreach(Object *obj,
825 int (*fn)(Object *child, void *opaque),
826 void *opaque, bool recurse)
32efc535 827{
b604a854
PF
828 GHashTableIter iter;
829 ObjectProperty *prop;
32efc535
PB
830 int ret = 0;
831
b604a854
PF
832 g_hash_table_iter_init(&iter, obj->properties);
833 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
32efc535 834 if (object_property_is_child(prop)) {
d714b8de
PC
835 Object *child = prop->opaque;
836
837 ret = fn(child, opaque);
32efc535
PB
838 if (ret != 0) {
839 break;
840 }
d714b8de
PC
841 if (recurse) {
842 do_object_child_foreach(child, fn, opaque, true);
843 }
32efc535
PB
844 }
845 }
846 return ret;
847}
848
d714b8de
PC
849int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
850 void *opaque)
851{
852 return do_object_child_foreach(obj, fn, opaque, false);
853}
854
855int object_child_foreach_recursive(Object *obj,
856 int (*fn)(Object *child, void *opaque),
857 void *opaque)
858{
859 return do_object_child_foreach(obj, fn, opaque, true);
860}
861
418ba9e5
AF
862static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
863{
864 GSList **list = opaque;
865
866 *list = g_slist_prepend(*list, klass);
867}
868
869GSList *object_class_get_list(const char *implements_type,
870 bool include_abstract)
871{
872 GSList *list = NULL;
873
874 object_class_foreach(object_class_get_list_tramp,
875 implements_type, include_abstract, &list);
876 return list;
877}
878
57c9fafe
AL
879void object_ref(Object *obj)
880{
8ffad850
PC
881 if (!obj) {
882 return;
883 }
8438a135 884 atomic_inc(&obj->ref);
57c9fafe
AL
885}
886
887void object_unref(Object *obj)
888{
8ffad850
PC
889 if (!obj) {
890 return;
891 }
8438a135 892 g_assert_cmpint(obj->ref, >, 0);
57c9fafe
AL
893
894 /* parent always holds a reference to its children */
f08c03f3 895 if (atomic_fetch_dec(&obj->ref) == 1) {
57c9fafe
AL
896 object_finalize(obj);
897 }
898}
899
64607d08
PB
900ObjectProperty *
901object_property_add(Object *obj, const char *name, const char *type,
902 ObjectPropertyAccessor *get,
903 ObjectPropertyAccessor *set,
904 ObjectPropertyRelease *release,
905 void *opaque, Error **errp)
57c9fafe 906{
54852b03 907 ObjectProperty *prop;
33965904
PC
908 size_t name_len = strlen(name);
909
910 if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
911 int i;
912 ObjectProperty *ret;
913 char *name_no_array = g_strdup(name);
914
915 name_no_array[name_len - 3] = '\0';
916 for (i = 0; ; ++i) {
917 char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
918
919 ret = object_property_add(obj, full_name, type, get, set,
920 release, opaque, NULL);
921 g_free(full_name);
922 if (ret) {
923 break;
924 }
925 }
926 g_free(name_no_array);
927 return ret;
928 }
54852b03 929
16bf7f52 930 if (object_property_find(obj, name, NULL) != NULL) {
b604a854 931 error_setg(errp, "attempt to add duplicate property '%s'"
16bf7f52
DB
932 " to object (type '%s')", name,
933 object_get_typename(obj));
b604a854 934 return NULL;
54852b03
PM
935 }
936
937 prop = g_malloc0(sizeof(*prop));
57c9fafe
AL
938
939 prop->name = g_strdup(name);
940 prop->type = g_strdup(type);
941
942 prop->get = get;
943 prop->set = set;
944 prop->release = release;
945 prop->opaque = opaque;
946
b604a854 947 g_hash_table_insert(obj->properties, prop->name, prop);
64607d08 948 return prop;
57c9fafe
AL
949}
950
16bf7f52
DB
951ObjectProperty *
952object_class_property_add(ObjectClass *klass,
953 const char *name,
954 const char *type,
955 ObjectPropertyAccessor *get,
956 ObjectPropertyAccessor *set,
957 ObjectPropertyRelease *release,
958 void *opaque,
959 Error **errp)
960{
961 ObjectProperty *prop;
962
963 if (object_class_property_find(klass, name, NULL) != NULL) {
964 error_setg(errp, "attempt to add duplicate property '%s'"
965 " to object (type '%s')", name,
966 object_class_get_name(klass));
967 return NULL;
968 }
969
970 prop = g_malloc0(sizeof(*prop));
971
972 prop->name = g_strdup(name);
973 prop->type = g_strdup(type);
974
975 prop->get = get;
976 prop->set = set;
977 prop->release = release;
978 prop->opaque = opaque;
979
980 g_hash_table_insert(klass->properties, g_strdup(name), prop);
981
982 return prop;
983}
984
89bfe000
PB
985ObjectProperty *object_property_find(Object *obj, const char *name,
986 Error **errp)
57c9fafe
AL
987{
988 ObjectProperty *prop;
16bf7f52
DB
989 ObjectClass *klass = object_get_class(obj);
990
991 prop = object_class_property_find(klass, name, NULL);
992 if (prop) {
993 return prop;
994 }
57c9fafe 995
b604a854
PF
996 prop = g_hash_table_lookup(obj->properties, name);
997 if (prop) {
998 return prop;
57c9fafe
AL
999 }
1000
f231b88d 1001 error_setg(errp, "Property '.%s' not found", name);
57c9fafe
AL
1002 return NULL;
1003}
1004
7746abd8
DB
1005void object_property_iter_init(ObjectPropertyIterator *iter,
1006 Object *obj)
a00c9482 1007{
7746abd8
DB
1008 g_hash_table_iter_init(&iter->iter, obj->properties);
1009 iter->nextclass = object_get_class(obj);
a00c9482
DB
1010}
1011
1012ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1013{
b604a854 1014 gpointer key, val;
16bf7f52
DB
1015 while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
1016 if (!iter->nextclass) {
1017 return NULL;
1018 }
1019 g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
1020 iter->nextclass = object_class_get_parent(iter->nextclass);
a00c9482 1021 }
b604a854 1022 return val;
a00c9482
DB
1023}
1024
16bf7f52
DB
1025ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
1026 Error **errp)
1027{
1028 ObjectProperty *prop;
1029 ObjectClass *parent_klass;
1030
1031 parent_klass = object_class_get_parent(klass);
1032 if (parent_klass) {
1033 prop = object_class_property_find(parent_klass, name, NULL);
1034 if (prop) {
1035 return prop;
1036 }
1037 }
1038
1039 prop = g_hash_table_lookup(klass->properties, name);
1040 if (!prop) {
1041 error_setg(errp, "Property '.%s' not found", name);
1042 }
1043 return prop;
1044}
1045
57c9fafe
AL
1046void object_property_del(Object *obj, const char *name, Error **errp)
1047{
b604a854
PF
1048 ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1049
1050 if (!prop) {
1051 error_setg(errp, "Property '.%s' not found", name);
0866aca1
AL
1052 return;
1053 }
57c9fafe 1054
0866aca1
AL
1055 if (prop->release) {
1056 prop->release(obj, name, prop->opaque);
1057 }
b604a854 1058 g_hash_table_remove(obj->properties, name);
57c9fafe
AL
1059}
1060
1061void object_property_get(Object *obj, Visitor *v, const char *name,
1062 Error **errp)
1063{
89bfe000 1064 ObjectProperty *prop = object_property_find(obj, name, errp);
57c9fafe 1065 if (prop == NULL) {
57c9fafe
AL
1066 return;
1067 }
1068
1069 if (!prop->get) {
c6bd8c70 1070 error_setg(errp, QERR_PERMISSION_DENIED);
57c9fafe 1071 } else {
d7bce999 1072 prop->get(obj, v, name, prop->opaque, errp);
57c9fafe
AL
1073 }
1074}
1075
1076void object_property_set(Object *obj, Visitor *v, const char *name,
1077 Error **errp)
1078{
89bfe000 1079 ObjectProperty *prop = object_property_find(obj, name, errp);
57c9fafe 1080 if (prop == NULL) {
57c9fafe
AL
1081 return;
1082 }
1083
1084 if (!prop->set) {
c6bd8c70 1085 error_setg(errp, QERR_PERMISSION_DENIED);
57c9fafe 1086 } else {
d7bce999 1087 prop->set(obj, v, name, prop->opaque, errp);
57c9fafe
AL
1088 }
1089}
1090
7b7b7d18
PB
1091void object_property_set_str(Object *obj, const char *value,
1092 const char *name, Error **errp)
1093{
1094 QString *qstr = qstring_from_str(value);
1095 object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
1096
1097 QDECREF(qstr);
1098}
1099
1100char *object_property_get_str(Object *obj, const char *name,
1101 Error **errp)
1102{
1103 QObject *ret = object_property_get_qobject(obj, name, errp);
1104 QString *qstring;
1105 char *retval;
1106
1107 if (!ret) {
1108 return NULL;
1109 }
1110 qstring = qobject_to_qstring(ret);
1111 if (!qstring) {
c6bd8c70 1112 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
7b7b7d18
PB
1113 retval = NULL;
1114 } else {
1115 retval = g_strdup(qstring_get_str(qstring));
1116 }
1117
1118 QDECREF(qstring);
1119 return retval;
1120}
1121
1d9c5a12
PB
1122void object_property_set_link(Object *obj, Object *value,
1123 const char *name, Error **errp)
1124{
d3c49316
PC
1125 if (value) {
1126 gchar *path = object_get_canonical_path(value);
1127 object_property_set_str(obj, path, name, errp);
1128 g_free(path);
1129 } else {
1130 object_property_set_str(obj, "", name, errp);
1131 }
1d9c5a12
PB
1132}
1133
1134Object *object_property_get_link(Object *obj, const char *name,
1135 Error **errp)
1136{
1137 char *str = object_property_get_str(obj, name, errp);
1138 Object *target = NULL;
1139
1140 if (str && *str) {
1141 target = object_resolve_path(str, NULL);
1142 if (!target) {
75158ebb
MA
1143 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1144 "Device '%s' not found", str);
1d9c5a12
PB
1145 }
1146 }
1147
1148 g_free(str);
1149 return target;
1150}
1151
7b7b7d18
PB
1152void object_property_set_bool(Object *obj, bool value,
1153 const char *name, Error **errp)
1154{
fc48ffc3 1155 QBool *qbool = qbool_from_bool(value);
7b7b7d18
PB
1156 object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
1157
1158 QDECREF(qbool);
1159}
1160
1161bool object_property_get_bool(Object *obj, const char *name,
1162 Error **errp)
1163{
1164 QObject *ret = object_property_get_qobject(obj, name, errp);
1165 QBool *qbool;
1166 bool retval;
1167
1168 if (!ret) {
1169 return false;
1170 }
1171 qbool = qobject_to_qbool(ret);
1172 if (!qbool) {
c6bd8c70 1173 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
7b7b7d18
PB
1174 retval = false;
1175 } else {
fc48ffc3 1176 retval = qbool_get_bool(qbool);
7b7b7d18
PB
1177 }
1178
1179 QDECREF(qbool);
1180 return retval;
1181}
1182
1183void object_property_set_int(Object *obj, int64_t value,
1184 const char *name, Error **errp)
1185{
1186 QInt *qint = qint_from_int(value);
1187 object_property_set_qobject(obj, QOBJECT(qint), name, errp);
1188
1189 QDECREF(qint);
1190}
1191
1192int64_t object_property_get_int(Object *obj, const char *name,
1193 Error **errp)
1194{
1195 QObject *ret = object_property_get_qobject(obj, name, errp);
1196 QInt *qint;
1197 int64_t retval;
1198
1199 if (!ret) {
1200 return -1;
1201 }
1202 qint = qobject_to_qint(ret);
1203 if (!qint) {
c6bd8c70 1204 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
7b7b7d18
PB
1205 retval = -1;
1206 } else {
1207 retval = qint_get_int(qint);
1208 }
1209
1210 QDECREF(qint);
1211 return retval;
b2cd7dee
PB
1212}
1213
a8e3fbed
DB
1214typedef struct EnumProperty {
1215 const char * const *strings;
1216 int (*get)(Object *, Error **);
1217 void (*set)(Object *, int, Error **);
1218} EnumProperty;
1219
1f21772d 1220int object_property_get_enum(Object *obj, const char *name,
a3590dac 1221 const char *typename, Error **errp)
1f21772d 1222{
4715d42e 1223 Error *err = NULL;
1f21772d
HT
1224 StringOutputVisitor *sov;
1225 StringInputVisitor *siv;
976620ac 1226 char *str;
1f21772d 1227 int ret;
a3590dac
DB
1228 ObjectProperty *prop = object_property_find(obj, name, errp);
1229 EnumProperty *enumprop;
1230
1231 if (prop == NULL) {
1232 return 0;
1233 }
1234
1235 if (!g_str_equal(prop->type, typename)) {
1236 error_setg(errp, "Property %s on %s is not '%s' enum type",
1237 name, object_class_get_name(
1238 object_get_class(obj)), typename);
1239 return 0;
1240 }
1241
1242 enumprop = prop->opaque;
1f21772d
HT
1243
1244 sov = string_output_visitor_new(false);
4715d42e
MA
1245 object_property_get(obj, string_output_get_visitor(sov), name, &err);
1246 if (err) {
1247 error_propagate(errp, err);
1248 string_output_visitor_cleanup(sov);
1249 return 0;
1250 }
976620ac
CF
1251 str = string_output_get_string(sov);
1252 siv = string_input_visitor_new(str);
1f21772d 1253 string_output_visitor_cleanup(sov);
51e72bc1 1254 visit_type_enum(string_input_get_visitor(siv), name, &ret,
337283df 1255 enumprop->strings, errp);
976620ac
CF
1256
1257 g_free(str);
1f21772d
HT
1258 string_input_visitor_cleanup(siv);
1259
1260 return ret;
1261}
1262
1263void object_property_get_uint16List(Object *obj, const char *name,
1264 uint16List **list, Error **errp)
1265{
4715d42e 1266 Error *err = NULL;
1f21772d
HT
1267 StringOutputVisitor *ov;
1268 StringInputVisitor *iv;
976620ac 1269 char *str;
1f21772d
HT
1270
1271 ov = string_output_visitor_new(false);
1272 object_property_get(obj, string_output_get_visitor(ov),
4715d42e
MA
1273 name, &err);
1274 if (err) {
1275 error_propagate(errp, err);
1276 goto out;
1277 }
976620ac
CF
1278 str = string_output_get_string(ov);
1279 iv = string_input_visitor_new(str);
51e72bc1 1280 visit_type_uint16List(string_input_get_visitor(iv), NULL, list, errp);
976620ac
CF
1281
1282 g_free(str);
1f21772d 1283 string_input_visitor_cleanup(iv);
4715d42e
MA
1284out:
1285 string_output_visitor_cleanup(ov);
1f21772d
HT
1286}
1287
b2cd7dee
PB
1288void object_property_parse(Object *obj, const char *string,
1289 const char *name, Error **errp)
1290{
f8b7f1a8
EB
1291 StringInputVisitor *siv;
1292 siv = string_input_visitor_new(string);
1293 object_property_set(obj, string_input_get_visitor(siv), name, errp);
b2cd7dee 1294
f8b7f1a8 1295 string_input_visitor_cleanup(siv);
b2cd7dee
PB
1296}
1297
0b7593e0 1298char *object_property_print(Object *obj, const char *name, bool human,
b2cd7dee
PB
1299 Error **errp)
1300{
f8b7f1a8 1301 StringOutputVisitor *sov;
3a53009f
GA
1302 char *string = NULL;
1303 Error *local_err = NULL;
b2cd7dee 1304
f8b7f1a8
EB
1305 sov = string_output_visitor_new(human);
1306 object_property_get(obj, string_output_get_visitor(sov), name, &local_err);
3a53009f
GA
1307 if (local_err) {
1308 error_propagate(errp, local_err);
1309 goto out;
1310 }
1311
f8b7f1a8 1312 string = string_output_get_string(sov);
3a53009f
GA
1313
1314out:
f8b7f1a8 1315 string_output_visitor_cleanup(sov);
b2cd7dee 1316 return string;
7b7b7d18
PB
1317}
1318
57c9fafe
AL
1319const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1320{
89bfe000 1321 ObjectProperty *prop = object_property_find(obj, name, errp);
57c9fafe 1322 if (prop == NULL) {
57c9fafe
AL
1323 return NULL;
1324 }
1325
1326 return prop->type;
1327}
1328
1329Object *object_get_root(void)
1330{
8b45d447 1331 static Object *root;
57c9fafe 1332
8b45d447
AL
1333 if (!root) {
1334 root = object_new("container");
57c9fafe
AL
1335 }
1336
8b45d447 1337 return root;
57c9fafe
AL
1338}
1339
bc2256c4
DB
1340Object *object_get_objects_root(void)
1341{
1342 return container_get(object_get_root(), "/objects");
1343}
1344
d7bce999
EB
1345static void object_get_child_property(Object *obj, Visitor *v,
1346 const char *name, void *opaque,
1347 Error **errp)
57c9fafe
AL
1348{
1349 Object *child = opaque;
1350 gchar *path;
1351
1352 path = object_get_canonical_path(child);
51e72bc1 1353 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1354 g_free(path);
1355}
1356
64607d08
PB
1357static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
1358{
1359 return opaque;
1360}
1361
db85b575
AL
1362static void object_finalize_child_property(Object *obj, const char *name,
1363 void *opaque)
1364{
1365 Object *child = opaque;
1366
bffc687d
PB
1367 if (child->class->unparent) {
1368 (child->class->unparent)(child);
1369 }
1370 child->parent = NULL;
db85b575
AL
1371 object_unref(child);
1372}
1373
57c9fafe
AL
1374void object_property_add_child(Object *obj, const char *name,
1375 Object *child, Error **errp)
1376{
b0ed5e9f 1377 Error *local_err = NULL;
57c9fafe 1378 gchar *type;
64607d08 1379 ObjectProperty *op;
57c9fafe 1380
8faa2f85
PC
1381 if (child->parent != NULL) {
1382 error_setg(errp, "child object is already parented");
1383 return;
1384 }
1385
57c9fafe
AL
1386 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
1387
64607d08
PB
1388 op = object_property_add(obj, name, type, object_get_child_property, NULL,
1389 object_finalize_child_property, child, &local_err);
b0ed5e9f
PB
1390 if (local_err) {
1391 error_propagate(errp, local_err);
1392 goto out;
1393 }
64607d08
PB
1394
1395 op->resolve = object_resolve_child_property;
57c9fafe 1396 object_ref(child);
57c9fafe
AL
1397 child->parent = obj;
1398
b0ed5e9f 1399out:
57c9fafe
AL
1400 g_free(type);
1401}
1402
39f72ef9
SH
1403void object_property_allow_set_link(Object *obj, const char *name,
1404 Object *val, Error **errp)
1405{
1406 /* Allow the link to be set, always */
1407}
1408
9561fda8
SH
1409typedef struct {
1410 Object **child;
39f72ef9 1411 void (*check)(Object *, const char *, Object *, Error **);
9561fda8
SH
1412 ObjectPropertyLinkFlags flags;
1413} LinkProperty;
1414
d7bce999
EB
1415static void object_get_link_property(Object *obj, Visitor *v,
1416 const char *name, void *opaque,
1417 Error **errp)
57c9fafe 1418{
9561fda8
SH
1419 LinkProperty *lprop = opaque;
1420 Object **child = lprop->child;
57c9fafe
AL
1421 gchar *path;
1422
1423 if (*child) {
1424 path = object_get_canonical_path(*child);
51e72bc1 1425 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1426 g_free(path);
1427 } else {
1428 path = (gchar *)"";
51e72bc1 1429 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1430 }
1431}
1432
f5ec6704
SH
1433/*
1434 * object_resolve_link:
1435 *
1436 * Lookup an object and ensure its type matches the link property type. This
1437 * is similar to object_resolve_path() except type verification against the
1438 * link property is performed.
1439 *
1440 * Returns: The matched object or NULL on path lookup failures.
1441 */
1442static Object *object_resolve_link(Object *obj, const char *name,
1443 const char *path, Error **errp)
1444{
1445 const char *type;
1446 gchar *target_type;
1447 bool ambiguous = false;
1448 Object *target;
1449
1450 /* Go from link<FOO> to FOO. */
1451 type = object_property_get_type(obj, name, NULL);
1452 target_type = g_strndup(&type[5], strlen(type) - 6);
1453 target = object_resolve_path_type(path, target_type, &ambiguous);
1454
1455 if (ambiguous) {
455b0fde
EB
1456 error_setg(errp, "Path '%s' does not uniquely identify an object",
1457 path);
f5ec6704
SH
1458 } else if (!target) {
1459 target = object_resolve_path(path, &ambiguous);
1460 if (target || ambiguous) {
c6bd8c70 1461 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
f5ec6704 1462 } else {
75158ebb
MA
1463 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1464 "Device '%s' not found", path);
f5ec6704
SH
1465 }
1466 target = NULL;
1467 }
1468 g_free(target_type);
1469
1470 return target;
1471}
1472
d7bce999
EB
1473static void object_set_link_property(Object *obj, Visitor *v,
1474 const char *name, void *opaque,
1475 Error **errp)
57c9fafe 1476{
c6aed983 1477 Error *local_err = NULL;
9561fda8
SH
1478 LinkProperty *prop = opaque;
1479 Object **child = prop->child;
c6aed983
SH
1480 Object *old_target = *child;
1481 Object *new_target = NULL;
1482 char *path = NULL;
57c9fafe 1483
51e72bc1 1484 visit_type_str(v, name, &path, &local_err);
57c9fafe 1485
c6aed983
SH
1486 if (!local_err && strcmp(path, "") != 0) {
1487 new_target = object_resolve_link(obj, name, path, &local_err);
57c9fafe
AL
1488 }
1489
1490 g_free(path);
c6aed983
SH
1491 if (local_err) {
1492 error_propagate(errp, local_err);
1493 return;
1494 }
f0cdc966 1495
39f72ef9
SH
1496 prop->check(obj, name, new_target, &local_err);
1497 if (local_err) {
1498 error_propagate(errp, local_err);
1499 return;
1500 }
1501
8ffad850 1502 object_ref(new_target);
c6aed983 1503 *child = new_target;
8ffad850 1504 object_unref(old_target);
57c9fafe
AL
1505}
1506
64607d08
PB
1507static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
1508{
1509 LinkProperty *lprop = opaque;
1510
1511 return *lprop->child;
1512}
1513
9561fda8
SH
1514static void object_release_link_property(Object *obj, const char *name,
1515 void *opaque)
1516{
1517 LinkProperty *prop = opaque;
1518
1519 if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) {
1520 object_unref(*prop->child);
1521 }
1522 g_free(prop);
1523}
1524
57c9fafe
AL
1525void object_property_add_link(Object *obj, const char *name,
1526 const char *type, Object **child,
39f72ef9
SH
1527 void (*check)(Object *, const char *,
1528 Object *, Error **),
9561fda8 1529 ObjectPropertyLinkFlags flags,
57c9fafe
AL
1530 Error **errp)
1531{
9561fda8
SH
1532 Error *local_err = NULL;
1533 LinkProperty *prop = g_malloc(sizeof(*prop));
57c9fafe 1534 gchar *full_type;
64607d08 1535 ObjectProperty *op;
57c9fafe 1536
9561fda8 1537 prop->child = child;
39f72ef9 1538 prop->check = check;
9561fda8
SH
1539 prop->flags = flags;
1540
57c9fafe
AL
1541 full_type = g_strdup_printf("link<%s>", type);
1542
64607d08
PB
1543 op = object_property_add(obj, name, full_type,
1544 object_get_link_property,
1545 check ? object_set_link_property : NULL,
1546 object_release_link_property,
1547 prop,
1548 &local_err);
9561fda8
SH
1549 if (local_err) {
1550 error_propagate(errp, local_err);
1551 g_free(prop);
64607d08 1552 goto out;
9561fda8 1553 }
57c9fafe 1554
64607d08
PB
1555 op->resolve = object_resolve_link_property;
1556
1557out:
57c9fafe
AL
1558 g_free(full_type);
1559}
1560
fb9e7e33
PB
1561void object_property_add_const_link(Object *obj, const char *name,
1562 Object *target, Error **errp)
1563{
1564 char *link_type;
1565 ObjectProperty *op;
1566
1567 link_type = g_strdup_printf("link<%s>", object_get_typename(target));
1568 op = object_property_add(obj, name, link_type,
1569 object_get_child_property, NULL,
1570 NULL, target, errp);
1571 if (op != NULL) {
1572 op->resolve = object_resolve_child_property;
1573 }
1574 g_free(link_type);
1575}
1576
11f590b1
SH
1577gchar *object_get_canonical_path_component(Object *obj)
1578{
1579 ObjectProperty *prop = NULL;
b604a854 1580 GHashTableIter iter;
11f590b1
SH
1581
1582 g_assert(obj);
1583 g_assert(obj->parent != NULL);
1584
b604a854
PF
1585 g_hash_table_iter_init(&iter, obj->parent->properties);
1586 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
11f590b1
SH
1587 if (!object_property_is_child(prop)) {
1588 continue;
1589 }
1590
1591 if (prop->opaque == obj) {
1592 return g_strdup(prop->name);
1593 }
1594 }
1595
1596 /* obj had a parent but was not a child, should never happen */
1597 g_assert_not_reached();
1598 return NULL;
1599}
1600
57c9fafe
AL
1601gchar *object_get_canonical_path(Object *obj)
1602{
1603 Object *root = object_get_root();
11f590b1 1604 char *newpath, *path = NULL;
57c9fafe
AL
1605
1606 while (obj != root) {
11f590b1 1607 char *component = object_get_canonical_path_component(obj);
57c9fafe 1608
11f590b1
SH
1609 if (path) {
1610 newpath = g_strdup_printf("%s/%s", component, path);
1611 g_free(component);
1612 g_free(path);
1613 path = newpath;
1614 } else {
1615 path = component;
57c9fafe
AL
1616 }
1617
57c9fafe
AL
1618 obj = obj->parent;
1619 }
1620
11f590b1 1621 newpath = g_strdup_printf("/%s", path ? path : "");
57c9fafe
AL
1622 g_free(path);
1623
1624 return newpath;
1625}
1626
3e84b483 1627Object *object_resolve_path_component(Object *parent, const gchar *part)
a612b2a6 1628{
89bfe000 1629 ObjectProperty *prop = object_property_find(parent, part, NULL);
a612b2a6
PB
1630 if (prop == NULL) {
1631 return NULL;
1632 }
1633
64607d08
PB
1634 if (prop->resolve) {
1635 return prop->resolve(parent, prop->opaque, part);
a612b2a6
PB
1636 } else {
1637 return NULL;
1638 }
1639}
1640
57c9fafe
AL
1641static Object *object_resolve_abs_path(Object *parent,
1642 gchar **parts,
02fe2db6 1643 const char *typename,
57c9fafe
AL
1644 int index)
1645{
57c9fafe
AL
1646 Object *child;
1647
1648 if (parts[index] == NULL) {
02fe2db6 1649 return object_dynamic_cast(parent, typename);
57c9fafe
AL
1650 }
1651
1652 if (strcmp(parts[index], "") == 0) {
02fe2db6 1653 return object_resolve_abs_path(parent, parts, typename, index + 1);
57c9fafe
AL
1654 }
1655
a612b2a6 1656 child = object_resolve_path_component(parent, parts[index]);
57c9fafe
AL
1657 if (!child) {
1658 return NULL;
1659 }
1660
02fe2db6 1661 return object_resolve_abs_path(child, parts, typename, index + 1);
57c9fafe
AL
1662}
1663
1664static Object *object_resolve_partial_path(Object *parent,
1665 gchar **parts,
02fe2db6 1666 const char *typename,
57c9fafe
AL
1667 bool *ambiguous)
1668{
1669 Object *obj;
b604a854 1670 GHashTableIter iter;
57c9fafe
AL
1671 ObjectProperty *prop;
1672
02fe2db6 1673 obj = object_resolve_abs_path(parent, parts, typename, 0);
57c9fafe 1674
b604a854
PF
1675 g_hash_table_iter_init(&iter, parent->properties);
1676 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
57c9fafe
AL
1677 Object *found;
1678
5d9d3f47 1679 if (!object_property_is_child(prop)) {
57c9fafe
AL
1680 continue;
1681 }
1682
02fe2db6
PB
1683 found = object_resolve_partial_path(prop->opaque, parts,
1684 typename, ambiguous);
57c9fafe
AL
1685 if (found) {
1686 if (obj) {
1687 if (ambiguous) {
1688 *ambiguous = true;
1689 }
1690 return NULL;
1691 }
1692 obj = found;
1693 }
1694
1695 if (ambiguous && *ambiguous) {
1696 return NULL;
1697 }
1698 }
1699
1700 return obj;
1701}
1702
02fe2db6
PB
1703Object *object_resolve_path_type(const char *path, const char *typename,
1704 bool *ambiguous)
57c9fafe 1705{
57c9fafe
AL
1706 Object *obj;
1707 gchar **parts;
1708
1709 parts = g_strsplit(path, "/", 0);
2e1103f6 1710 assert(parts);
57c9fafe 1711
2e1103f6 1712 if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
57c9fafe
AL
1713 if (ambiguous) {
1714 *ambiguous = false;
1715 }
02fe2db6
PB
1716 obj = object_resolve_partial_path(object_get_root(), parts,
1717 typename, ambiguous);
57c9fafe 1718 } else {
02fe2db6 1719 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
57c9fafe
AL
1720 }
1721
1722 g_strfreev(parts);
1723
1724 return obj;
1725}
1726
02fe2db6
PB
1727Object *object_resolve_path(const char *path, bool *ambiguous)
1728{
1729 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1730}
1731
57c9fafe
AL
1732typedef struct StringProperty
1733{
1734 char *(*get)(Object *, Error **);
1735 void (*set)(Object *, const char *, Error **);
1736} StringProperty;
1737
d7bce999
EB
1738static void property_get_str(Object *obj, Visitor *v, const char *name,
1739 void *opaque, Error **errp)
57c9fafe
AL
1740{
1741 StringProperty *prop = opaque;
1742 char *value;
e1c8237d 1743 Error *err = NULL;
57c9fafe 1744
e1c8237d
MA
1745 value = prop->get(obj, &err);
1746 if (err) {
1747 error_propagate(errp, err);
1748 return;
57c9fafe 1749 }
e1c8237d 1750
51e72bc1 1751 visit_type_str(v, name, &value, errp);
e1c8237d 1752 g_free(value);
57c9fafe
AL
1753}
1754
d7bce999
EB
1755static void property_set_str(Object *obj, Visitor *v, const char *name,
1756 void *opaque, Error **errp)
57c9fafe
AL
1757{
1758 StringProperty *prop = opaque;
1759 char *value;
1760 Error *local_err = NULL;
1761
51e72bc1 1762 visit_type_str(v, name, &value, &local_err);
57c9fafe
AL
1763 if (local_err) {
1764 error_propagate(errp, local_err);
1765 return;
1766 }
1767
1768 prop->set(obj, value, errp);
1769 g_free(value);
1770}
1771
7b7b7d18
PB
1772static void property_release_str(Object *obj, const char *name,
1773 void *opaque)
57c9fafe
AL
1774{
1775 StringProperty *prop = opaque;
1776 g_free(prop);
1777}
1778
1779void object_property_add_str(Object *obj, const char *name,
1780 char *(*get)(Object *, Error **),
1781 void (*set)(Object *, const char *, Error **),
1782 Error **errp)
1783{
a01aedc8 1784 Error *local_err = NULL;
57c9fafe
AL
1785 StringProperty *prop = g_malloc0(sizeof(*prop));
1786
1787 prop->get = get;
1788 prop->set = set;
1789
1790 object_property_add(obj, name, "string",
7b7b7d18
PB
1791 get ? property_get_str : NULL,
1792 set ? property_set_str : NULL,
1793 property_release_str,
a01aedc8
SH
1794 prop, &local_err);
1795 if (local_err) {
1796 error_propagate(errp, local_err);
1797 g_free(prop);
1798 }
57c9fafe 1799}
745549c8 1800
16bf7f52
DB
1801void object_class_property_add_str(ObjectClass *klass, const char *name,
1802 char *(*get)(Object *, Error **),
1803 void (*set)(Object *, const char *,
1804 Error **),
1805 Error **errp)
1806{
1807 Error *local_err = NULL;
1808 StringProperty *prop = g_malloc0(sizeof(*prop));
1809
1810 prop->get = get;
1811 prop->set = set;
1812
1813 object_class_property_add(klass, name, "string",
1814 get ? property_get_str : NULL,
1815 set ? property_set_str : NULL,
1816 property_release_str,
1817 prop, &local_err);
1818 if (local_err) {
1819 error_propagate(errp, local_err);
1820 g_free(prop);
1821 }
1822}
1823
0e558843
AL
1824typedef struct BoolProperty
1825{
1826 bool (*get)(Object *, Error **);
1827 void (*set)(Object *, bool, Error **);
1828} BoolProperty;
1829
d7bce999
EB
1830static void property_get_bool(Object *obj, Visitor *v, const char *name,
1831 void *opaque, Error **errp)
0e558843
AL
1832{
1833 BoolProperty *prop = opaque;
1834 bool value;
4715d42e
MA
1835 Error *err = NULL;
1836
1837 value = prop->get(obj, &err);
1838 if (err) {
1839 error_propagate(errp, err);
1840 return;
1841 }
0e558843 1842
51e72bc1 1843 visit_type_bool(v, name, &value, errp);
0e558843
AL
1844}
1845
d7bce999
EB
1846static void property_set_bool(Object *obj, Visitor *v, const char *name,
1847 void *opaque, Error **errp)
0e558843
AL
1848{
1849 BoolProperty *prop = opaque;
1850 bool value;
1851 Error *local_err = NULL;
1852
51e72bc1 1853 visit_type_bool(v, name, &value, &local_err);
0e558843
AL
1854 if (local_err) {
1855 error_propagate(errp, local_err);
1856 return;
1857 }
1858
1859 prop->set(obj, value, errp);
1860}
1861
1862static void property_release_bool(Object *obj, const char *name,
1863 void *opaque)
1864{
1865 BoolProperty *prop = opaque;
1866 g_free(prop);
1867}
1868
1869void object_property_add_bool(Object *obj, const char *name,
1870 bool (*get)(Object *, Error **),
1871 void (*set)(Object *, bool, Error **),
1872 Error **errp)
1873{
a01aedc8 1874 Error *local_err = NULL;
0e558843
AL
1875 BoolProperty *prop = g_malloc0(sizeof(*prop));
1876
1877 prop->get = get;
1878 prop->set = set;
1879
1880 object_property_add(obj, name, "bool",
1881 get ? property_get_bool : NULL,
1882 set ? property_set_bool : NULL,
1883 property_release_bool,
a01aedc8
SH
1884 prop, &local_err);
1885 if (local_err) {
1886 error_propagate(errp, local_err);
1887 g_free(prop);
1888 }
0e558843
AL
1889}
1890
16bf7f52
DB
1891void object_class_property_add_bool(ObjectClass *klass, const char *name,
1892 bool (*get)(Object *, Error **),
1893 void (*set)(Object *, bool, Error **),
1894 Error **errp)
1895{
1896 Error *local_err = NULL;
1897 BoolProperty *prop = g_malloc0(sizeof(*prop));
1898
1899 prop->get = get;
1900 prop->set = set;
1901
1902 object_class_property_add(klass, name, "bool",
1903 get ? property_get_bool : NULL,
1904 set ? property_set_bool : NULL,
1905 property_release_bool,
1906 prop, &local_err);
1907 if (local_err) {
1908 error_propagate(errp, local_err);
1909 g_free(prop);
1910 }
1911}
1912
d7bce999
EB
1913static void property_get_enum(Object *obj, Visitor *v, const char *name,
1914 void *opaque, Error **errp)
a8e3fbed
DB
1915{
1916 EnumProperty *prop = opaque;
1917 int value;
4715d42e
MA
1918 Error *err = NULL;
1919
1920 value = prop->get(obj, &err);
1921 if (err) {
1922 error_propagate(errp, err);
1923 return;
1924 }
a8e3fbed 1925
337283df 1926 visit_type_enum(v, name, &value, prop->strings, errp);
a8e3fbed
DB
1927}
1928
d7bce999
EB
1929static void property_set_enum(Object *obj, Visitor *v, const char *name,
1930 void *opaque, Error **errp)
a8e3fbed
DB
1931{
1932 EnumProperty *prop = opaque;
1933 int value;
4715d42e 1934 Error *err = NULL;
a8e3fbed 1935
337283df 1936 visit_type_enum(v, name, &value, prop->strings, &err);
4715d42e
MA
1937 if (err) {
1938 error_propagate(errp, err);
1939 return;
1940 }
a8e3fbed
DB
1941 prop->set(obj, value, errp);
1942}
1943
1944static void property_release_enum(Object *obj, const char *name,
1945 void *opaque)
1946{
1947 EnumProperty *prop = opaque;
1948 g_free(prop);
1949}
1950
1951void object_property_add_enum(Object *obj, const char *name,
1952 const char *typename,
1953 const char * const *strings,
1954 int (*get)(Object *, Error **),
1955 void (*set)(Object *, int, Error **),
1956 Error **errp)
1957{
1958 Error *local_err = NULL;
1959 EnumProperty *prop = g_malloc(sizeof(*prop));
1960
1961 prop->strings = strings;
1962 prop->get = get;
1963 prop->set = set;
1964
1965 object_property_add(obj, name, typename,
1966 get ? property_get_enum : NULL,
1967 set ? property_set_enum : NULL,
1968 property_release_enum,
1969 prop, &local_err);
1970 if (local_err) {
1971 error_propagate(errp, local_err);
1972 g_free(prop);
1973 }
1974}
1975
16bf7f52
DB
1976void object_class_property_add_enum(ObjectClass *klass, const char *name,
1977 const char *typename,
1978 const char * const *strings,
1979 int (*get)(Object *, Error **),
1980 void (*set)(Object *, int, Error **),
1981 Error **errp)
1982{
1983 Error *local_err = NULL;
1984 EnumProperty *prop = g_malloc(sizeof(*prop));
1985
1986 prop->strings = strings;
1987 prop->get = get;
1988 prop->set = set;
1989
1990 object_class_property_add(klass, name, typename,
1991 get ? property_get_enum : NULL,
1992 set ? property_set_enum : NULL,
1993 property_release_enum,
1994 prop, &local_err);
1995 if (local_err) {
1996 error_propagate(errp, local_err);
1997 g_free(prop);
1998 }
1999}
2000
8e099d14
DG
2001typedef struct TMProperty {
2002 void (*get)(Object *, struct tm *, Error **);
2003} TMProperty;
2004
d7bce999
EB
2005static void property_get_tm(Object *obj, Visitor *v, const char *name,
2006 void *opaque, Error **errp)
8e099d14
DG
2007{
2008 TMProperty *prop = opaque;
2009 Error *err = NULL;
2010 struct tm value;
2011
2012 prop->get(obj, &value, &err);
2013 if (err) {
2014 goto out;
2015 }
2016
337283df 2017 visit_start_struct(v, name, NULL, 0, &err);
8e099d14
DG
2018 if (err) {
2019 goto out;
2020 }
51e72bc1 2021 visit_type_int32(v, "tm_year", &value.tm_year, &err);
8e099d14
DG
2022 if (err) {
2023 goto out_end;
2024 }
51e72bc1 2025 visit_type_int32(v, "tm_mon", &value.tm_mon, &err);
8e099d14
DG
2026 if (err) {
2027 goto out_end;
2028 }
51e72bc1 2029 visit_type_int32(v, "tm_mday", &value.tm_mday, &err);
8e099d14
DG
2030 if (err) {
2031 goto out_end;
2032 }
51e72bc1 2033 visit_type_int32(v, "tm_hour", &value.tm_hour, &err);
8e099d14
DG
2034 if (err) {
2035 goto out_end;
2036 }
51e72bc1 2037 visit_type_int32(v, "tm_min", &value.tm_min, &err);
8e099d14
DG
2038 if (err) {
2039 goto out_end;
2040 }
51e72bc1 2041 visit_type_int32(v, "tm_sec", &value.tm_sec, &err);
8e099d14
DG
2042 if (err) {
2043 goto out_end;
2044 }
15c2f669 2045 visit_check_struct(v, &err);
8e099d14 2046out_end:
15c2f669 2047 visit_end_struct(v);
8e099d14
DG
2048out:
2049 error_propagate(errp, err);
2050
2051}
2052
2053static void property_release_tm(Object *obj, const char *name,
2054 void *opaque)
2055{
2056 TMProperty *prop = opaque;
2057 g_free(prop);
2058}
2059
2060void object_property_add_tm(Object *obj, const char *name,
2061 void (*get)(Object *, struct tm *, Error **),
2062 Error **errp)
2063{
2064 Error *local_err = NULL;
2065 TMProperty *prop = g_malloc0(sizeof(*prop));
2066
2067 prop->get = get;
2068
2069 object_property_add(obj, name, "struct tm",
2070 get ? property_get_tm : NULL, NULL,
2071 property_release_tm,
2072 prop, &local_err);
2073 if (local_err) {
2074 error_propagate(errp, local_err);
2075 g_free(prop);
2076 }
2077}
2078
16bf7f52
DB
2079void object_class_property_add_tm(ObjectClass *klass, const char *name,
2080 void (*get)(Object *, struct tm *, Error **),
2081 Error **errp)
2082{
2083 Error *local_err = NULL;
2084 TMProperty *prop = g_malloc0(sizeof(*prop));
2085
2086 prop->get = get;
2087
2088 object_class_property_add(klass, name, "struct tm",
2089 get ? property_get_tm : NULL, NULL,
2090 property_release_tm,
2091 prop, &local_err);
2092 if (local_err) {
2093 error_propagate(errp, local_err);
2094 g_free(prop);
2095 }
2096}
2097
2f262e06
PB
2098static char *qdev_get_type(Object *obj, Error **errp)
2099{
2100 return g_strdup(object_get_typename(obj));
2101}
2102
d7bce999
EB
2103static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2104 void *opaque, Error **errp)
e732ea63
MT
2105{
2106 uint8_t value = *(uint8_t *)opaque;
51e72bc1 2107 visit_type_uint8(v, name, &value, errp);
e732ea63
MT
2108}
2109
d7bce999
EB
2110static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2111 void *opaque, Error **errp)
e732ea63
MT
2112{
2113 uint16_t value = *(uint16_t *)opaque;
51e72bc1 2114 visit_type_uint16(v, name, &value, errp);
e732ea63
MT
2115}
2116
d7bce999
EB
2117static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2118 void *opaque, Error **errp)
e732ea63
MT
2119{
2120 uint32_t value = *(uint32_t *)opaque;
51e72bc1 2121 visit_type_uint32(v, name, &value, errp);
e732ea63
MT
2122}
2123
d7bce999
EB
2124static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2125 void *opaque, Error **errp)
e732ea63
MT
2126{
2127 uint64_t value = *(uint64_t *)opaque;
51e72bc1 2128 visit_type_uint64(v, name, &value, errp);
e732ea63
MT
2129}
2130
2131void object_property_add_uint8_ptr(Object *obj, const char *name,
2132 const uint8_t *v, Error **errp)
2133{
2134 object_property_add(obj, name, "uint8", property_get_uint8_ptr,
2135 NULL, NULL, (void *)v, errp);
2136}
2137
16bf7f52
DB
2138void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2139 const uint8_t *v, Error **errp)
2140{
2141 object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
2142 NULL, NULL, (void *)v, errp);
2143}
2144
e732ea63
MT
2145void object_property_add_uint16_ptr(Object *obj, const char *name,
2146 const uint16_t *v, Error **errp)
2147{
2148 object_property_add(obj, name, "uint16", property_get_uint16_ptr,
2149 NULL, NULL, (void *)v, errp);
2150}
2151
16bf7f52
DB
2152void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2153 const uint16_t *v, Error **errp)
2154{
2155 object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
2156 NULL, NULL, (void *)v, errp);
2157}
2158
e732ea63
MT
2159void object_property_add_uint32_ptr(Object *obj, const char *name,
2160 const uint32_t *v, Error **errp)
2161{
2162 object_property_add(obj, name, "uint32", property_get_uint32_ptr,
2163 NULL, NULL, (void *)v, errp);
2164}
2165
16bf7f52
DB
2166void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2167 const uint32_t *v, Error **errp)
2168{
2169 object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
2170 NULL, NULL, (void *)v, errp);
2171}
2172
e732ea63
MT
2173void object_property_add_uint64_ptr(Object *obj, const char *name,
2174 const uint64_t *v, Error **errp)
2175{
2176 object_property_add(obj, name, "uint64", property_get_uint64_ptr,
2177 NULL, NULL, (void *)v, errp);
2178}
2179
16bf7f52
DB
2180void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2181 const uint64_t *v, Error **errp)
2182{
2183 object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
2184 NULL, NULL, (void *)v, errp);
2185}
2186
ef7c7ff6
SH
2187typedef struct {
2188 Object *target_obj;
1590d266 2189 char *target_name;
ef7c7ff6
SH
2190} AliasProperty;
2191
d7bce999
EB
2192static void property_get_alias(Object *obj, Visitor *v, const char *name,
2193 void *opaque, Error **errp)
ef7c7ff6
SH
2194{
2195 AliasProperty *prop = opaque;
2196
2197 object_property_get(prop->target_obj, v, prop->target_name, errp);
2198}
2199
d7bce999
EB
2200static void property_set_alias(Object *obj, Visitor *v, const char *name,
2201 void *opaque, Error **errp)
ef7c7ff6
SH
2202{
2203 AliasProperty *prop = opaque;
2204
2205 object_property_set(prop->target_obj, v, prop->target_name, errp);
2206}
2207
64607d08
PB
2208static Object *property_resolve_alias(Object *obj, void *opaque,
2209 const gchar *part)
2210{
2211 AliasProperty *prop = opaque;
2212
2213 return object_resolve_path_component(prop->target_obj, prop->target_name);
2214}
2215
ef7c7ff6
SH
2216static void property_release_alias(Object *obj, const char *name, void *opaque)
2217{
2218 AliasProperty *prop = opaque;
2219
1590d266 2220 g_free(prop->target_name);
ef7c7ff6
SH
2221 g_free(prop);
2222}
2223
2224void object_property_add_alias(Object *obj, const char *name,
2225 Object *target_obj, const char *target_name,
2226 Error **errp)
2227{
2228 AliasProperty *prop;
64607d08 2229 ObjectProperty *op;
ef7c7ff6 2230 ObjectProperty *target_prop;
d190698e 2231 gchar *prop_type;
8ae9a9ef 2232 Error *local_err = NULL;
ef7c7ff6
SH
2233
2234 target_prop = object_property_find(target_obj, target_name, errp);
2235 if (!target_prop) {
2236 return;
2237 }
2238
d190698e
PB
2239 if (object_property_is_child(target_prop)) {
2240 prop_type = g_strdup_printf("link%s",
2241 target_prop->type + strlen("child"));
2242 } else {
2243 prop_type = g_strdup(target_prop->type);
2244 }
2245
ef7c7ff6
SH
2246 prop = g_malloc(sizeof(*prop));
2247 prop->target_obj = target_obj;
1590d266 2248 prop->target_name = g_strdup(target_name);
ef7c7ff6 2249
d190698e 2250 op = object_property_add(obj, name, prop_type,
64607d08
PB
2251 property_get_alias,
2252 property_set_alias,
2253 property_release_alias,
8ae9a9ef
GA
2254 prop, &local_err);
2255 if (local_err) {
2256 error_propagate(errp, local_err);
2257 g_free(prop);
2258 goto out;
2259 }
64607d08 2260 op->resolve = property_resolve_alias;
d190698e 2261
a18bb417 2262 object_property_set_description(obj, op->name,
80742642
GA
2263 target_prop->description,
2264 &error_abort);
2265
8ae9a9ef 2266out:
d190698e 2267 g_free(prop_type);
ef7c7ff6
SH
2268}
2269
80742642
GA
2270void object_property_set_description(Object *obj, const char *name,
2271 const char *description, Error **errp)
2272{
2273 ObjectProperty *op;
2274
2275 op = object_property_find(obj, name, errp);
2276 if (!op) {
2277 return;
2278 }
2279
2280 g_free(op->description);
2281 op->description = g_strdup(description);
2282}
2283
16bf7f52
DB
2284void object_class_property_set_description(ObjectClass *klass,
2285 const char *name,
2286 const char *description,
2287 Error **errp)
2288{
2289 ObjectProperty *op;
2290
2291 op = g_hash_table_lookup(klass->properties, name);
2292 if (!op) {
2293 error_setg(errp, "Property '.%s' not found", name);
2294 return;
2295 }
2296
2297 g_free(op->description);
2298 op->description = g_strdup(description);
2299}
2300
2f262e06
PB
2301static void object_instance_init(Object *obj)
2302{
2303 object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
2304}
2305
745549c8
PB
2306static void register_types(void)
2307{
2308 static TypeInfo interface_info = {
2309 .name = TYPE_INTERFACE,
33e95c63 2310 .class_size = sizeof(InterfaceClass),
745549c8
PB
2311 .abstract = true,
2312 };
2313
2314 static TypeInfo object_info = {
2315 .name = TYPE_OBJECT,
2316 .instance_size = sizeof(Object),
2f262e06 2317 .instance_init = object_instance_init,
745549c8
PB
2318 .abstract = true,
2319 };
2320
049cb3cf
PB
2321 type_interface = type_register_internal(&interface_info);
2322 type_register_internal(&object_info);
745549c8
PB
2323}
2324
2325type_init(register_types)