]> git.proxmox.com Git - mirror_qemu.git/blame - qom/object.c
qmp-input-visitor: Favor new visit_free() function
[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 1224 StringOutputVisitor *sov;
7a0525c7 1225 Visitor *v;
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 1251 str = string_output_get_string(sov);
1f21772d 1252 string_output_visitor_cleanup(sov);
7a0525c7
EB
1253 v = string_input_visitor_new(str);
1254 visit_type_enum(v, name, &ret, enumprop->strings, errp);
976620ac
CF
1255
1256 g_free(str);
7a0525c7 1257 visit_free(v);
1f21772d
HT
1258
1259 return ret;
1260}
1261
1262void object_property_get_uint16List(Object *obj, const char *name,
1263 uint16List **list, Error **errp)
1264{
4715d42e 1265 Error *err = NULL;
1f21772d 1266 StringOutputVisitor *ov;
7a0525c7 1267 Visitor *v;
976620ac 1268 char *str;
1f21772d
HT
1269
1270 ov = string_output_visitor_new(false);
1271 object_property_get(obj, string_output_get_visitor(ov),
4715d42e
MA
1272 name, &err);
1273 if (err) {
1274 error_propagate(errp, err);
1275 goto out;
1276 }
976620ac 1277 str = string_output_get_string(ov);
7a0525c7
EB
1278 v = string_input_visitor_new(str);
1279 visit_type_uint16List(v, NULL, list, errp);
976620ac
CF
1280
1281 g_free(str);
7a0525c7 1282 visit_free(v);
4715d42e
MA
1283out:
1284 string_output_visitor_cleanup(ov);
1f21772d
HT
1285}
1286
b2cd7dee
PB
1287void object_property_parse(Object *obj, const char *string,
1288 const char *name, Error **errp)
1289{
7a0525c7
EB
1290 Visitor *v = string_input_visitor_new(string);
1291 object_property_set(obj, v, name, errp);
1292 visit_free(v);
b2cd7dee
PB
1293}
1294
0b7593e0 1295char *object_property_print(Object *obj, const char *name, bool human,
b2cd7dee
PB
1296 Error **errp)
1297{
f8b7f1a8 1298 StringOutputVisitor *sov;
3a53009f
GA
1299 char *string = NULL;
1300 Error *local_err = NULL;
b2cd7dee 1301
f8b7f1a8
EB
1302 sov = string_output_visitor_new(human);
1303 object_property_get(obj, string_output_get_visitor(sov), name, &local_err);
3a53009f
GA
1304 if (local_err) {
1305 error_propagate(errp, local_err);
1306 goto out;
1307 }
1308
f8b7f1a8 1309 string = string_output_get_string(sov);
3a53009f
GA
1310
1311out:
f8b7f1a8 1312 string_output_visitor_cleanup(sov);
b2cd7dee 1313 return string;
7b7b7d18
PB
1314}
1315
57c9fafe
AL
1316const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1317{
89bfe000 1318 ObjectProperty *prop = object_property_find(obj, name, errp);
57c9fafe 1319 if (prop == NULL) {
57c9fafe
AL
1320 return NULL;
1321 }
1322
1323 return prop->type;
1324}
1325
1326Object *object_get_root(void)
1327{
8b45d447 1328 static Object *root;
57c9fafe 1329
8b45d447
AL
1330 if (!root) {
1331 root = object_new("container");
57c9fafe
AL
1332 }
1333
8b45d447 1334 return root;
57c9fafe
AL
1335}
1336
bc2256c4
DB
1337Object *object_get_objects_root(void)
1338{
1339 return container_get(object_get_root(), "/objects");
1340}
1341
d7bce999
EB
1342static void object_get_child_property(Object *obj, Visitor *v,
1343 const char *name, void *opaque,
1344 Error **errp)
57c9fafe
AL
1345{
1346 Object *child = opaque;
1347 gchar *path;
1348
1349 path = object_get_canonical_path(child);
51e72bc1 1350 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1351 g_free(path);
1352}
1353
64607d08
PB
1354static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
1355{
1356 return opaque;
1357}
1358
db85b575
AL
1359static void object_finalize_child_property(Object *obj, const char *name,
1360 void *opaque)
1361{
1362 Object *child = opaque;
1363
bffc687d
PB
1364 if (child->class->unparent) {
1365 (child->class->unparent)(child);
1366 }
1367 child->parent = NULL;
db85b575
AL
1368 object_unref(child);
1369}
1370
57c9fafe
AL
1371void object_property_add_child(Object *obj, const char *name,
1372 Object *child, Error **errp)
1373{
b0ed5e9f 1374 Error *local_err = NULL;
57c9fafe 1375 gchar *type;
64607d08 1376 ObjectProperty *op;
57c9fafe 1377
8faa2f85
PC
1378 if (child->parent != NULL) {
1379 error_setg(errp, "child object is already parented");
1380 return;
1381 }
1382
57c9fafe
AL
1383 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
1384
64607d08
PB
1385 op = object_property_add(obj, name, type, object_get_child_property, NULL,
1386 object_finalize_child_property, child, &local_err);
b0ed5e9f
PB
1387 if (local_err) {
1388 error_propagate(errp, local_err);
1389 goto out;
1390 }
64607d08
PB
1391
1392 op->resolve = object_resolve_child_property;
57c9fafe 1393 object_ref(child);
57c9fafe
AL
1394 child->parent = obj;
1395
b0ed5e9f 1396out:
57c9fafe
AL
1397 g_free(type);
1398}
1399
39f72ef9
SH
1400void object_property_allow_set_link(Object *obj, const char *name,
1401 Object *val, Error **errp)
1402{
1403 /* Allow the link to be set, always */
1404}
1405
9561fda8
SH
1406typedef struct {
1407 Object **child;
39f72ef9 1408 void (*check)(Object *, const char *, Object *, Error **);
9561fda8
SH
1409 ObjectPropertyLinkFlags flags;
1410} LinkProperty;
1411
d7bce999
EB
1412static void object_get_link_property(Object *obj, Visitor *v,
1413 const char *name, void *opaque,
1414 Error **errp)
57c9fafe 1415{
9561fda8
SH
1416 LinkProperty *lprop = opaque;
1417 Object **child = lprop->child;
57c9fafe
AL
1418 gchar *path;
1419
1420 if (*child) {
1421 path = object_get_canonical_path(*child);
51e72bc1 1422 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1423 g_free(path);
1424 } else {
1425 path = (gchar *)"";
51e72bc1 1426 visit_type_str(v, name, &path, errp);
57c9fafe
AL
1427 }
1428}
1429
f5ec6704
SH
1430/*
1431 * object_resolve_link:
1432 *
1433 * Lookup an object and ensure its type matches the link property type. This
1434 * is similar to object_resolve_path() except type verification against the
1435 * link property is performed.
1436 *
1437 * Returns: The matched object or NULL on path lookup failures.
1438 */
1439static Object *object_resolve_link(Object *obj, const char *name,
1440 const char *path, Error **errp)
1441{
1442 const char *type;
1443 gchar *target_type;
1444 bool ambiguous = false;
1445 Object *target;
1446
1447 /* Go from link<FOO> to FOO. */
1448 type = object_property_get_type(obj, name, NULL);
1449 target_type = g_strndup(&type[5], strlen(type) - 6);
1450 target = object_resolve_path_type(path, target_type, &ambiguous);
1451
1452 if (ambiguous) {
455b0fde
EB
1453 error_setg(errp, "Path '%s' does not uniquely identify an object",
1454 path);
f5ec6704
SH
1455 } else if (!target) {
1456 target = object_resolve_path(path, &ambiguous);
1457 if (target || ambiguous) {
c6bd8c70 1458 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
f5ec6704 1459 } else {
75158ebb
MA
1460 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1461 "Device '%s' not found", path);
f5ec6704
SH
1462 }
1463 target = NULL;
1464 }
1465 g_free(target_type);
1466
1467 return target;
1468}
1469
d7bce999
EB
1470static void object_set_link_property(Object *obj, Visitor *v,
1471 const char *name, void *opaque,
1472 Error **errp)
57c9fafe 1473{
c6aed983 1474 Error *local_err = NULL;
9561fda8
SH
1475 LinkProperty *prop = opaque;
1476 Object **child = prop->child;
c6aed983
SH
1477 Object *old_target = *child;
1478 Object *new_target = NULL;
1479 char *path = NULL;
57c9fafe 1480
51e72bc1 1481 visit_type_str(v, name, &path, &local_err);
57c9fafe 1482
c6aed983
SH
1483 if (!local_err && strcmp(path, "") != 0) {
1484 new_target = object_resolve_link(obj, name, path, &local_err);
57c9fafe
AL
1485 }
1486
1487 g_free(path);
c6aed983
SH
1488 if (local_err) {
1489 error_propagate(errp, local_err);
1490 return;
1491 }
f0cdc966 1492
39f72ef9
SH
1493 prop->check(obj, name, new_target, &local_err);
1494 if (local_err) {
1495 error_propagate(errp, local_err);
1496 return;
1497 }
1498
8ffad850 1499 object_ref(new_target);
c6aed983 1500 *child = new_target;
8ffad850 1501 object_unref(old_target);
57c9fafe
AL
1502}
1503
64607d08
PB
1504static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
1505{
1506 LinkProperty *lprop = opaque;
1507
1508 return *lprop->child;
1509}
1510
9561fda8
SH
1511static void object_release_link_property(Object *obj, const char *name,
1512 void *opaque)
1513{
1514 LinkProperty *prop = opaque;
1515
1516 if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) {
1517 object_unref(*prop->child);
1518 }
1519 g_free(prop);
1520}
1521
57c9fafe
AL
1522void object_property_add_link(Object *obj, const char *name,
1523 const char *type, Object **child,
39f72ef9
SH
1524 void (*check)(Object *, const char *,
1525 Object *, Error **),
9561fda8 1526 ObjectPropertyLinkFlags flags,
57c9fafe
AL
1527 Error **errp)
1528{
9561fda8
SH
1529 Error *local_err = NULL;
1530 LinkProperty *prop = g_malloc(sizeof(*prop));
57c9fafe 1531 gchar *full_type;
64607d08 1532 ObjectProperty *op;
57c9fafe 1533
9561fda8 1534 prop->child = child;
39f72ef9 1535 prop->check = check;
9561fda8
SH
1536 prop->flags = flags;
1537
57c9fafe
AL
1538 full_type = g_strdup_printf("link<%s>", type);
1539
64607d08
PB
1540 op = object_property_add(obj, name, full_type,
1541 object_get_link_property,
1542 check ? object_set_link_property : NULL,
1543 object_release_link_property,
1544 prop,
1545 &local_err);
9561fda8
SH
1546 if (local_err) {
1547 error_propagate(errp, local_err);
1548 g_free(prop);
64607d08 1549 goto out;
9561fda8 1550 }
57c9fafe 1551
64607d08
PB
1552 op->resolve = object_resolve_link_property;
1553
1554out:
57c9fafe
AL
1555 g_free(full_type);
1556}
1557
fb9e7e33
PB
1558void object_property_add_const_link(Object *obj, const char *name,
1559 Object *target, Error **errp)
1560{
1561 char *link_type;
1562 ObjectProperty *op;
1563
1564 link_type = g_strdup_printf("link<%s>", object_get_typename(target));
1565 op = object_property_add(obj, name, link_type,
1566 object_get_child_property, NULL,
1567 NULL, target, errp);
1568 if (op != NULL) {
1569 op->resolve = object_resolve_child_property;
1570 }
1571 g_free(link_type);
1572}
1573
11f590b1
SH
1574gchar *object_get_canonical_path_component(Object *obj)
1575{
1576 ObjectProperty *prop = NULL;
b604a854 1577 GHashTableIter iter;
11f590b1
SH
1578
1579 g_assert(obj);
1580 g_assert(obj->parent != NULL);
1581
b604a854
PF
1582 g_hash_table_iter_init(&iter, obj->parent->properties);
1583 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
11f590b1
SH
1584 if (!object_property_is_child(prop)) {
1585 continue;
1586 }
1587
1588 if (prop->opaque == obj) {
1589 return g_strdup(prop->name);
1590 }
1591 }
1592
1593 /* obj had a parent but was not a child, should never happen */
1594 g_assert_not_reached();
1595 return NULL;
1596}
1597
57c9fafe
AL
1598gchar *object_get_canonical_path(Object *obj)
1599{
1600 Object *root = object_get_root();
11f590b1 1601 char *newpath, *path = NULL;
57c9fafe
AL
1602
1603 while (obj != root) {
11f590b1 1604 char *component = object_get_canonical_path_component(obj);
57c9fafe 1605
11f590b1
SH
1606 if (path) {
1607 newpath = g_strdup_printf("%s/%s", component, path);
1608 g_free(component);
1609 g_free(path);
1610 path = newpath;
1611 } else {
1612 path = component;
57c9fafe
AL
1613 }
1614
57c9fafe
AL
1615 obj = obj->parent;
1616 }
1617
11f590b1 1618 newpath = g_strdup_printf("/%s", path ? path : "");
57c9fafe
AL
1619 g_free(path);
1620
1621 return newpath;
1622}
1623
3e84b483 1624Object *object_resolve_path_component(Object *parent, const gchar *part)
a612b2a6 1625{
89bfe000 1626 ObjectProperty *prop = object_property_find(parent, part, NULL);
a612b2a6
PB
1627 if (prop == NULL) {
1628 return NULL;
1629 }
1630
64607d08
PB
1631 if (prop->resolve) {
1632 return prop->resolve(parent, prop->opaque, part);
a612b2a6
PB
1633 } else {
1634 return NULL;
1635 }
1636}
1637
57c9fafe
AL
1638static Object *object_resolve_abs_path(Object *parent,
1639 gchar **parts,
02fe2db6 1640 const char *typename,
57c9fafe
AL
1641 int index)
1642{
57c9fafe
AL
1643 Object *child;
1644
1645 if (parts[index] == NULL) {
02fe2db6 1646 return object_dynamic_cast(parent, typename);
57c9fafe
AL
1647 }
1648
1649 if (strcmp(parts[index], "") == 0) {
02fe2db6 1650 return object_resolve_abs_path(parent, parts, typename, index + 1);
57c9fafe
AL
1651 }
1652
a612b2a6 1653 child = object_resolve_path_component(parent, parts[index]);
57c9fafe
AL
1654 if (!child) {
1655 return NULL;
1656 }
1657
02fe2db6 1658 return object_resolve_abs_path(child, parts, typename, index + 1);
57c9fafe
AL
1659}
1660
1661static Object *object_resolve_partial_path(Object *parent,
1662 gchar **parts,
02fe2db6 1663 const char *typename,
57c9fafe
AL
1664 bool *ambiguous)
1665{
1666 Object *obj;
b604a854 1667 GHashTableIter iter;
57c9fafe
AL
1668 ObjectProperty *prop;
1669
02fe2db6 1670 obj = object_resolve_abs_path(parent, parts, typename, 0);
57c9fafe 1671
b604a854
PF
1672 g_hash_table_iter_init(&iter, parent->properties);
1673 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
57c9fafe
AL
1674 Object *found;
1675
5d9d3f47 1676 if (!object_property_is_child(prop)) {
57c9fafe
AL
1677 continue;
1678 }
1679
02fe2db6
PB
1680 found = object_resolve_partial_path(prop->opaque, parts,
1681 typename, ambiguous);
57c9fafe
AL
1682 if (found) {
1683 if (obj) {
1684 if (ambiguous) {
1685 *ambiguous = true;
1686 }
1687 return NULL;
1688 }
1689 obj = found;
1690 }
1691
1692 if (ambiguous && *ambiguous) {
1693 return NULL;
1694 }
1695 }
1696
1697 return obj;
1698}
1699
02fe2db6
PB
1700Object *object_resolve_path_type(const char *path, const char *typename,
1701 bool *ambiguous)
57c9fafe 1702{
57c9fafe
AL
1703 Object *obj;
1704 gchar **parts;
1705
1706 parts = g_strsplit(path, "/", 0);
2e1103f6 1707 assert(parts);
57c9fafe 1708
2e1103f6 1709 if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
57c9fafe
AL
1710 if (ambiguous) {
1711 *ambiguous = false;
1712 }
02fe2db6
PB
1713 obj = object_resolve_partial_path(object_get_root(), parts,
1714 typename, ambiguous);
57c9fafe 1715 } else {
02fe2db6 1716 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
57c9fafe
AL
1717 }
1718
1719 g_strfreev(parts);
1720
1721 return obj;
1722}
1723
02fe2db6
PB
1724Object *object_resolve_path(const char *path, bool *ambiguous)
1725{
1726 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1727}
1728
57c9fafe
AL
1729typedef struct StringProperty
1730{
1731 char *(*get)(Object *, Error **);
1732 void (*set)(Object *, const char *, Error **);
1733} StringProperty;
1734
d7bce999
EB
1735static void property_get_str(Object *obj, Visitor *v, const char *name,
1736 void *opaque, Error **errp)
57c9fafe
AL
1737{
1738 StringProperty *prop = opaque;
1739 char *value;
e1c8237d 1740 Error *err = NULL;
57c9fafe 1741
e1c8237d
MA
1742 value = prop->get(obj, &err);
1743 if (err) {
1744 error_propagate(errp, err);
1745 return;
57c9fafe 1746 }
e1c8237d 1747
51e72bc1 1748 visit_type_str(v, name, &value, errp);
e1c8237d 1749 g_free(value);
57c9fafe
AL
1750}
1751
d7bce999
EB
1752static void property_set_str(Object *obj, Visitor *v, const char *name,
1753 void *opaque, Error **errp)
57c9fafe
AL
1754{
1755 StringProperty *prop = opaque;
1756 char *value;
1757 Error *local_err = NULL;
1758
51e72bc1 1759 visit_type_str(v, name, &value, &local_err);
57c9fafe
AL
1760 if (local_err) {
1761 error_propagate(errp, local_err);
1762 return;
1763 }
1764
1765 prop->set(obj, value, errp);
1766 g_free(value);
1767}
1768
7b7b7d18
PB
1769static void property_release_str(Object *obj, const char *name,
1770 void *opaque)
57c9fafe
AL
1771{
1772 StringProperty *prop = opaque;
1773 g_free(prop);
1774}
1775
1776void object_property_add_str(Object *obj, const char *name,
1777 char *(*get)(Object *, Error **),
1778 void (*set)(Object *, const char *, Error **),
1779 Error **errp)
1780{
a01aedc8 1781 Error *local_err = NULL;
57c9fafe
AL
1782 StringProperty *prop = g_malloc0(sizeof(*prop));
1783
1784 prop->get = get;
1785 prop->set = set;
1786
1787 object_property_add(obj, name, "string",
7b7b7d18
PB
1788 get ? property_get_str : NULL,
1789 set ? property_set_str : NULL,
1790 property_release_str,
a01aedc8
SH
1791 prop, &local_err);
1792 if (local_err) {
1793 error_propagate(errp, local_err);
1794 g_free(prop);
1795 }
57c9fafe 1796}
745549c8 1797
16bf7f52
DB
1798void object_class_property_add_str(ObjectClass *klass, const char *name,
1799 char *(*get)(Object *, Error **),
1800 void (*set)(Object *, const char *,
1801 Error **),
1802 Error **errp)
1803{
1804 Error *local_err = NULL;
1805 StringProperty *prop = g_malloc0(sizeof(*prop));
1806
1807 prop->get = get;
1808 prop->set = set;
1809
1810 object_class_property_add(klass, name, "string",
1811 get ? property_get_str : NULL,
1812 set ? property_set_str : NULL,
1813 property_release_str,
1814 prop, &local_err);
1815 if (local_err) {
1816 error_propagate(errp, local_err);
1817 g_free(prop);
1818 }
1819}
1820
0e558843
AL
1821typedef struct BoolProperty
1822{
1823 bool (*get)(Object *, Error **);
1824 void (*set)(Object *, bool, Error **);
1825} BoolProperty;
1826
d7bce999
EB
1827static void property_get_bool(Object *obj, Visitor *v, const char *name,
1828 void *opaque, Error **errp)
0e558843
AL
1829{
1830 BoolProperty *prop = opaque;
1831 bool value;
4715d42e
MA
1832 Error *err = NULL;
1833
1834 value = prop->get(obj, &err);
1835 if (err) {
1836 error_propagate(errp, err);
1837 return;
1838 }
0e558843 1839
51e72bc1 1840 visit_type_bool(v, name, &value, errp);
0e558843
AL
1841}
1842
d7bce999
EB
1843static void property_set_bool(Object *obj, Visitor *v, const char *name,
1844 void *opaque, Error **errp)
0e558843
AL
1845{
1846 BoolProperty *prop = opaque;
1847 bool value;
1848 Error *local_err = NULL;
1849
51e72bc1 1850 visit_type_bool(v, name, &value, &local_err);
0e558843
AL
1851 if (local_err) {
1852 error_propagate(errp, local_err);
1853 return;
1854 }
1855
1856 prop->set(obj, value, errp);
1857}
1858
1859static void property_release_bool(Object *obj, const char *name,
1860 void *opaque)
1861{
1862 BoolProperty *prop = opaque;
1863 g_free(prop);
1864}
1865
1866void object_property_add_bool(Object *obj, const char *name,
1867 bool (*get)(Object *, Error **),
1868 void (*set)(Object *, bool, Error **),
1869 Error **errp)
1870{
a01aedc8 1871 Error *local_err = NULL;
0e558843
AL
1872 BoolProperty *prop = g_malloc0(sizeof(*prop));
1873
1874 prop->get = get;
1875 prop->set = set;
1876
1877 object_property_add(obj, name, "bool",
1878 get ? property_get_bool : NULL,
1879 set ? property_set_bool : NULL,
1880 property_release_bool,
a01aedc8
SH
1881 prop, &local_err);
1882 if (local_err) {
1883 error_propagate(errp, local_err);
1884 g_free(prop);
1885 }
0e558843
AL
1886}
1887
16bf7f52
DB
1888void object_class_property_add_bool(ObjectClass *klass, const char *name,
1889 bool (*get)(Object *, Error **),
1890 void (*set)(Object *, bool, Error **),
1891 Error **errp)
1892{
1893 Error *local_err = NULL;
1894 BoolProperty *prop = g_malloc0(sizeof(*prop));
1895
1896 prop->get = get;
1897 prop->set = set;
1898
1899 object_class_property_add(klass, name, "bool",
1900 get ? property_get_bool : NULL,
1901 set ? property_set_bool : NULL,
1902 property_release_bool,
1903 prop, &local_err);
1904 if (local_err) {
1905 error_propagate(errp, local_err);
1906 g_free(prop);
1907 }
1908}
1909
d7bce999
EB
1910static void property_get_enum(Object *obj, Visitor *v, const char *name,
1911 void *opaque, Error **errp)
a8e3fbed
DB
1912{
1913 EnumProperty *prop = opaque;
1914 int value;
4715d42e
MA
1915 Error *err = NULL;
1916
1917 value = prop->get(obj, &err);
1918 if (err) {
1919 error_propagate(errp, err);
1920 return;
1921 }
a8e3fbed 1922
337283df 1923 visit_type_enum(v, name, &value, prop->strings, errp);
a8e3fbed
DB
1924}
1925
d7bce999
EB
1926static void property_set_enum(Object *obj, Visitor *v, const char *name,
1927 void *opaque, Error **errp)
a8e3fbed
DB
1928{
1929 EnumProperty *prop = opaque;
1930 int value;
4715d42e 1931 Error *err = NULL;
a8e3fbed 1932
337283df 1933 visit_type_enum(v, name, &value, prop->strings, &err);
4715d42e
MA
1934 if (err) {
1935 error_propagate(errp, err);
1936 return;
1937 }
a8e3fbed
DB
1938 prop->set(obj, value, errp);
1939}
1940
1941static void property_release_enum(Object *obj, const char *name,
1942 void *opaque)
1943{
1944 EnumProperty *prop = opaque;
1945 g_free(prop);
1946}
1947
1948void object_property_add_enum(Object *obj, const char *name,
1949 const char *typename,
1950 const char * const *strings,
1951 int (*get)(Object *, Error **),
1952 void (*set)(Object *, int, Error **),
1953 Error **errp)
1954{
1955 Error *local_err = NULL;
1956 EnumProperty *prop = g_malloc(sizeof(*prop));
1957
1958 prop->strings = strings;
1959 prop->get = get;
1960 prop->set = set;
1961
1962 object_property_add(obj, name, typename,
1963 get ? property_get_enum : NULL,
1964 set ? property_set_enum : NULL,
1965 property_release_enum,
1966 prop, &local_err);
1967 if (local_err) {
1968 error_propagate(errp, local_err);
1969 g_free(prop);
1970 }
1971}
1972
16bf7f52
DB
1973void object_class_property_add_enum(ObjectClass *klass, const char *name,
1974 const char *typename,
1975 const char * const *strings,
1976 int (*get)(Object *, Error **),
1977 void (*set)(Object *, int, Error **),
1978 Error **errp)
1979{
1980 Error *local_err = NULL;
1981 EnumProperty *prop = g_malloc(sizeof(*prop));
1982
1983 prop->strings = strings;
1984 prop->get = get;
1985 prop->set = set;
1986
1987 object_class_property_add(klass, name, typename,
1988 get ? property_get_enum : NULL,
1989 set ? property_set_enum : NULL,
1990 property_release_enum,
1991 prop, &local_err);
1992 if (local_err) {
1993 error_propagate(errp, local_err);
1994 g_free(prop);
1995 }
1996}
1997
8e099d14
DG
1998typedef struct TMProperty {
1999 void (*get)(Object *, struct tm *, Error **);
2000} TMProperty;
2001
d7bce999
EB
2002static void property_get_tm(Object *obj, Visitor *v, const char *name,
2003 void *opaque, Error **errp)
8e099d14
DG
2004{
2005 TMProperty *prop = opaque;
2006 Error *err = NULL;
2007 struct tm value;
2008
2009 prop->get(obj, &value, &err);
2010 if (err) {
2011 goto out;
2012 }
2013
337283df 2014 visit_start_struct(v, name, NULL, 0, &err);
8e099d14
DG
2015 if (err) {
2016 goto out;
2017 }
51e72bc1 2018 visit_type_int32(v, "tm_year", &value.tm_year, &err);
8e099d14
DG
2019 if (err) {
2020 goto out_end;
2021 }
51e72bc1 2022 visit_type_int32(v, "tm_mon", &value.tm_mon, &err);
8e099d14
DG
2023 if (err) {
2024 goto out_end;
2025 }
51e72bc1 2026 visit_type_int32(v, "tm_mday", &value.tm_mday, &err);
8e099d14
DG
2027 if (err) {
2028 goto out_end;
2029 }
51e72bc1 2030 visit_type_int32(v, "tm_hour", &value.tm_hour, &err);
8e099d14
DG
2031 if (err) {
2032 goto out_end;
2033 }
51e72bc1 2034 visit_type_int32(v, "tm_min", &value.tm_min, &err);
8e099d14
DG
2035 if (err) {
2036 goto out_end;
2037 }
51e72bc1 2038 visit_type_int32(v, "tm_sec", &value.tm_sec, &err);
8e099d14
DG
2039 if (err) {
2040 goto out_end;
2041 }
15c2f669 2042 visit_check_struct(v, &err);
8e099d14 2043out_end:
1158bb2a 2044 visit_end_struct(v, NULL);
8e099d14
DG
2045out:
2046 error_propagate(errp, err);
2047
2048}
2049
2050static void property_release_tm(Object *obj, const char *name,
2051 void *opaque)
2052{
2053 TMProperty *prop = opaque;
2054 g_free(prop);
2055}
2056
2057void object_property_add_tm(Object *obj, const char *name,
2058 void (*get)(Object *, struct tm *, Error **),
2059 Error **errp)
2060{
2061 Error *local_err = NULL;
2062 TMProperty *prop = g_malloc0(sizeof(*prop));
2063
2064 prop->get = get;
2065
2066 object_property_add(obj, name, "struct tm",
2067 get ? property_get_tm : NULL, NULL,
2068 property_release_tm,
2069 prop, &local_err);
2070 if (local_err) {
2071 error_propagate(errp, local_err);
2072 g_free(prop);
2073 }
2074}
2075
16bf7f52
DB
2076void object_class_property_add_tm(ObjectClass *klass, const char *name,
2077 void (*get)(Object *, struct tm *, Error **),
2078 Error **errp)
2079{
2080 Error *local_err = NULL;
2081 TMProperty *prop = g_malloc0(sizeof(*prop));
2082
2083 prop->get = get;
2084
2085 object_class_property_add(klass, name, "struct tm",
2086 get ? property_get_tm : NULL, NULL,
2087 property_release_tm,
2088 prop, &local_err);
2089 if (local_err) {
2090 error_propagate(errp, local_err);
2091 g_free(prop);
2092 }
2093}
2094
2f262e06
PB
2095static char *qdev_get_type(Object *obj, Error **errp)
2096{
2097 return g_strdup(object_get_typename(obj));
2098}
2099
d7bce999
EB
2100static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2101 void *opaque, Error **errp)
e732ea63
MT
2102{
2103 uint8_t value = *(uint8_t *)opaque;
51e72bc1 2104 visit_type_uint8(v, name, &value, errp);
e732ea63
MT
2105}
2106
d7bce999
EB
2107static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2108 void *opaque, Error **errp)
e732ea63
MT
2109{
2110 uint16_t value = *(uint16_t *)opaque;
51e72bc1 2111 visit_type_uint16(v, name, &value, errp);
e732ea63
MT
2112}
2113
d7bce999
EB
2114static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2115 void *opaque, Error **errp)
e732ea63
MT
2116{
2117 uint32_t value = *(uint32_t *)opaque;
51e72bc1 2118 visit_type_uint32(v, name, &value, errp);
e732ea63
MT
2119}
2120
d7bce999
EB
2121static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2122 void *opaque, Error **errp)
e732ea63
MT
2123{
2124 uint64_t value = *(uint64_t *)opaque;
51e72bc1 2125 visit_type_uint64(v, name, &value, errp);
e732ea63
MT
2126}
2127
2128void object_property_add_uint8_ptr(Object *obj, const char *name,
2129 const uint8_t *v, Error **errp)
2130{
2131 object_property_add(obj, name, "uint8", property_get_uint8_ptr,
2132 NULL, NULL, (void *)v, errp);
2133}
2134
16bf7f52
DB
2135void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2136 const uint8_t *v, Error **errp)
2137{
2138 object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
2139 NULL, NULL, (void *)v, errp);
2140}
2141
e732ea63
MT
2142void object_property_add_uint16_ptr(Object *obj, const char *name,
2143 const uint16_t *v, Error **errp)
2144{
2145 object_property_add(obj, name, "uint16", property_get_uint16_ptr,
2146 NULL, NULL, (void *)v, errp);
2147}
2148
16bf7f52
DB
2149void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2150 const uint16_t *v, Error **errp)
2151{
2152 object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
2153 NULL, NULL, (void *)v, errp);
2154}
2155
e732ea63
MT
2156void object_property_add_uint32_ptr(Object *obj, const char *name,
2157 const uint32_t *v, Error **errp)
2158{
2159 object_property_add(obj, name, "uint32", property_get_uint32_ptr,
2160 NULL, NULL, (void *)v, errp);
2161}
2162
16bf7f52
DB
2163void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2164 const uint32_t *v, Error **errp)
2165{
2166 object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
2167 NULL, NULL, (void *)v, errp);
2168}
2169
e732ea63
MT
2170void object_property_add_uint64_ptr(Object *obj, const char *name,
2171 const uint64_t *v, Error **errp)
2172{
2173 object_property_add(obj, name, "uint64", property_get_uint64_ptr,
2174 NULL, NULL, (void *)v, errp);
2175}
2176
16bf7f52
DB
2177void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2178 const uint64_t *v, Error **errp)
2179{
2180 object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
2181 NULL, NULL, (void *)v, errp);
2182}
2183
ef7c7ff6
SH
2184typedef struct {
2185 Object *target_obj;
1590d266 2186 char *target_name;
ef7c7ff6
SH
2187} AliasProperty;
2188
d7bce999
EB
2189static void property_get_alias(Object *obj, Visitor *v, const char *name,
2190 void *opaque, Error **errp)
ef7c7ff6
SH
2191{
2192 AliasProperty *prop = opaque;
2193
2194 object_property_get(prop->target_obj, v, prop->target_name, errp);
2195}
2196
d7bce999
EB
2197static void property_set_alias(Object *obj, Visitor *v, const char *name,
2198 void *opaque, Error **errp)
ef7c7ff6
SH
2199{
2200 AliasProperty *prop = opaque;
2201
2202 object_property_set(prop->target_obj, v, prop->target_name, errp);
2203}
2204
64607d08
PB
2205static Object *property_resolve_alias(Object *obj, void *opaque,
2206 const gchar *part)
2207{
2208 AliasProperty *prop = opaque;
2209
2210 return object_resolve_path_component(prop->target_obj, prop->target_name);
2211}
2212
ef7c7ff6
SH
2213static void property_release_alias(Object *obj, const char *name, void *opaque)
2214{
2215 AliasProperty *prop = opaque;
2216
1590d266 2217 g_free(prop->target_name);
ef7c7ff6
SH
2218 g_free(prop);
2219}
2220
2221void object_property_add_alias(Object *obj, const char *name,
2222 Object *target_obj, const char *target_name,
2223 Error **errp)
2224{
2225 AliasProperty *prop;
64607d08 2226 ObjectProperty *op;
ef7c7ff6 2227 ObjectProperty *target_prop;
d190698e 2228 gchar *prop_type;
8ae9a9ef 2229 Error *local_err = NULL;
ef7c7ff6
SH
2230
2231 target_prop = object_property_find(target_obj, target_name, errp);
2232 if (!target_prop) {
2233 return;
2234 }
2235
d190698e
PB
2236 if (object_property_is_child(target_prop)) {
2237 prop_type = g_strdup_printf("link%s",
2238 target_prop->type + strlen("child"));
2239 } else {
2240 prop_type = g_strdup(target_prop->type);
2241 }
2242
ef7c7ff6
SH
2243 prop = g_malloc(sizeof(*prop));
2244 prop->target_obj = target_obj;
1590d266 2245 prop->target_name = g_strdup(target_name);
ef7c7ff6 2246
d190698e 2247 op = object_property_add(obj, name, prop_type,
64607d08
PB
2248 property_get_alias,
2249 property_set_alias,
2250 property_release_alias,
8ae9a9ef
GA
2251 prop, &local_err);
2252 if (local_err) {
2253 error_propagate(errp, local_err);
2254 g_free(prop);
2255 goto out;
2256 }
64607d08 2257 op->resolve = property_resolve_alias;
d190698e 2258
a18bb417 2259 object_property_set_description(obj, op->name,
80742642
GA
2260 target_prop->description,
2261 &error_abort);
2262
8ae9a9ef 2263out:
d190698e 2264 g_free(prop_type);
ef7c7ff6
SH
2265}
2266
80742642
GA
2267void object_property_set_description(Object *obj, const char *name,
2268 const char *description, Error **errp)
2269{
2270 ObjectProperty *op;
2271
2272 op = object_property_find(obj, name, errp);
2273 if (!op) {
2274 return;
2275 }
2276
2277 g_free(op->description);
2278 op->description = g_strdup(description);
2279}
2280
16bf7f52
DB
2281void object_class_property_set_description(ObjectClass *klass,
2282 const char *name,
2283 const char *description,
2284 Error **errp)
2285{
2286 ObjectProperty *op;
2287
2288 op = g_hash_table_lookup(klass->properties, name);
2289 if (!op) {
2290 error_setg(errp, "Property '.%s' not found", name);
2291 return;
2292 }
2293
2294 g_free(op->description);
2295 op->description = g_strdup(description);
2296}
2297
2f262e06
PB
2298static void object_instance_init(Object *obj)
2299{
2300 object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
2301}
2302
745549c8
PB
2303static void register_types(void)
2304{
2305 static TypeInfo interface_info = {
2306 .name = TYPE_INTERFACE,
33e95c63 2307 .class_size = sizeof(InterfaceClass),
745549c8
PB
2308 .abstract = true,
2309 };
2310
2311 static TypeInfo object_info = {
2312 .name = TYPE_OBJECT,
2313 .instance_size = sizeof(Object),
2f262e06 2314 .instance_init = object_instance_init,
745549c8
PB
2315 .abstract = true,
2316 };
2317
049cb3cf
PB
2318 type_interface = type_register_internal(&interface_info);
2319 type_register_internal(&object_info);
745549c8
PB
2320}
2321
2322type_init(register_types)