]> git.proxmox.com Git - qemu.git/blob - qom/object.c
qom: Introduce object_property_is_{child,link}()
[qemu.git] / qom / object.c
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
13 #include "qemu/object.h"
14 #include "qemu-common.h"
15 #include "qapi/qapi-visit-core.h"
16 #include "qapi/string-input-visitor.h"
17 #include "qapi/string-output-visitor.h"
18
19 /* TODO: replace QObject with a simpler visitor to avoid a dependency
20 * of the QOM core on QObject? */
21 #include "qemu/qom-qobject.h"
22 #include "qobject.h"
23 #include "qbool.h"
24 #include "qint.h"
25 #include "qstring.h"
26
27 #define MAX_INTERFACES 32
28
29 typedef struct InterfaceImpl InterfaceImpl;
30 typedef struct TypeImpl TypeImpl;
31
32 struct InterfaceImpl
33 {
34 const char *parent;
35 void (*interface_initfn)(ObjectClass *class, void *data);
36 TypeImpl *type;
37 };
38
39 struct TypeImpl
40 {
41 const char *name;
42
43 size_t class_size;
44
45 size_t instance_size;
46
47 void (*class_init)(ObjectClass *klass, void *data);
48 void (*class_finalize)(ObjectClass *klass, void *data);
49
50 void *class_data;
51
52 void (*instance_init)(Object *obj);
53 void (*instance_finalize)(Object *obj);
54
55 bool abstract;
56
57 const char *parent;
58 TypeImpl *parent_type;
59
60 ObjectClass *class;
61
62 int num_interfaces;
63 InterfaceImpl interfaces[MAX_INTERFACES];
64 };
65
66 typedef struct Interface
67 {
68 Object parent;
69 Object *obj;
70 } Interface;
71
72 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
73
74 static Type type_interface;
75
76 static GHashTable *type_table_get(void)
77 {
78 static GHashTable *type_table;
79
80 if (type_table == NULL) {
81 type_table = g_hash_table_new(g_str_hash, g_str_equal);
82 }
83
84 return type_table;
85 }
86
87 static void type_table_add(TypeImpl *ti)
88 {
89 g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
90 }
91
92 static TypeImpl *type_table_lookup(const char *name)
93 {
94 return g_hash_table_lookup(type_table_get(), name);
95 }
96
97 TypeImpl *type_register(const TypeInfo *info)
98 {
99 TypeImpl *ti = g_malloc0(sizeof(*ti));
100
101 g_assert(info->name != NULL);
102
103 if (type_table_lookup(info->name) != NULL) {
104 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
105 abort();
106 }
107
108 ti->name = g_strdup(info->name);
109 ti->parent = g_strdup(info->parent);
110
111 ti->class_size = info->class_size;
112 ti->instance_size = info->instance_size;
113
114 ti->class_init = info->class_init;
115 ti->class_finalize = info->class_finalize;
116 ti->class_data = info->class_data;
117
118 ti->instance_init = info->instance_init;
119 ti->instance_finalize = info->instance_finalize;
120
121 ti->abstract = info->abstract;
122
123 if (info->interfaces) {
124 int i;
125
126 for (i = 0; info->interfaces[i].type; i++) {
127 ti->interfaces[i].parent = info->interfaces[i].type;
128 ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
129 ti->num_interfaces++;
130 }
131 }
132
133 type_table_add(ti);
134
135 return ti;
136 }
137
138 TypeImpl *type_register_static(const TypeInfo *info)
139 {
140 return type_register(info);
141 }
142
143 static TypeImpl *type_get_by_name(const char *name)
144 {
145 if (name == NULL) {
146 return NULL;
147 }
148
149 return type_table_lookup(name);
150 }
151
152 static TypeImpl *type_get_parent(TypeImpl *type)
153 {
154 if (!type->parent_type && type->parent) {
155 type->parent_type = type_get_by_name(type->parent);
156 g_assert(type->parent_type != NULL);
157 }
158
159 return type->parent_type;
160 }
161
162 static bool type_has_parent(TypeImpl *type)
163 {
164 return (type->parent != NULL);
165 }
166
167 static size_t type_class_get_size(TypeImpl *ti)
168 {
169 if (ti->class_size) {
170 return ti->class_size;
171 }
172
173 if (type_has_parent(ti)) {
174 return type_class_get_size(type_get_parent(ti));
175 }
176
177 return sizeof(ObjectClass);
178 }
179
180 static size_t type_object_get_size(TypeImpl *ti)
181 {
182 if (ti->instance_size) {
183 return ti->instance_size;
184 }
185
186 if (type_has_parent(ti)) {
187 return type_object_get_size(type_get_parent(ti));
188 }
189
190 return 0;
191 }
192
193 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
194 {
195 TypeInfo info = {
196 .instance_size = sizeof(Interface),
197 .parent = iface->parent,
198 .class_size = sizeof(InterfaceClass),
199 .class_init = iface->interface_initfn,
200 .abstract = true,
201 };
202 char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
203
204 info.name = name;
205 iface->type = type_register(&info);
206 g_free(name);
207 }
208
209 static void type_initialize(TypeImpl *ti)
210 {
211 size_t class_size = sizeof(ObjectClass);
212 int i;
213
214 if (ti->class) {
215 return;
216 }
217
218 ti->class_size = type_class_get_size(ti);
219 ti->instance_size = type_object_get_size(ti);
220
221 ti->class = g_malloc0(ti->class_size);
222 ti->class->type = ti;
223
224 if (type_has_parent(ti)) {
225 TypeImpl *parent = type_get_parent(ti);
226
227 type_initialize(parent);
228
229 class_size = parent->class_size;
230 g_assert(parent->class_size <= ti->class_size);
231
232 memcpy((void *)ti->class + sizeof(ObjectClass),
233 (void *)parent->class + sizeof(ObjectClass),
234 parent->class_size - sizeof(ObjectClass));
235 }
236
237 memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
238
239 for (i = 0; i < ti->num_interfaces; i++) {
240 type_class_interface_init(ti, &ti->interfaces[i]);
241 }
242
243 if (ti->class_init) {
244 ti->class_init(ti->class, ti->class_data);
245 }
246 }
247
248 static void object_interface_init(Object *obj, InterfaceImpl *iface)
249 {
250 TypeImpl *ti = iface->type;
251 Interface *iface_obj;
252
253 iface_obj = INTERFACE(object_new(ti->name));
254 iface_obj->obj = obj;
255
256 obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
257 }
258
259 static void object_init_with_type(Object *obj, TypeImpl *ti)
260 {
261 int i;
262
263 if (type_has_parent(ti)) {
264 object_init_with_type(obj, type_get_parent(ti));
265 }
266
267 for (i = 0; i < ti->num_interfaces; i++) {
268 object_interface_init(obj, &ti->interfaces[i]);
269 }
270
271 if (ti->instance_init) {
272 ti->instance_init(obj);
273 }
274 }
275
276 void object_initialize_with_type(void *data, TypeImpl *type)
277 {
278 Object *obj = data;
279
280 g_assert(type != NULL);
281 type_initialize(type);
282
283 g_assert(type->instance_size >= sizeof(Object));
284 g_assert(type->abstract == false);
285
286 memset(obj, 0, type->instance_size);
287 obj->class = type->class;
288 QTAILQ_INIT(&obj->properties);
289 object_init_with_type(obj, type);
290 }
291
292 void object_initialize(void *data, const char *typename)
293 {
294 TypeImpl *type = type_get_by_name(typename);
295
296 object_initialize_with_type(data, type);
297 }
298
299 static inline bool object_property_is_child(ObjectProperty *prop)
300 {
301 return strstart(prop->type, "child<", NULL);
302 }
303
304 static inline bool object_property_is_link(ObjectProperty *prop)
305 {
306 return strstart(prop->type, "link<", NULL);
307 }
308
309 static void object_property_del_all(Object *obj)
310 {
311 while (!QTAILQ_EMPTY(&obj->properties)) {
312 ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
313
314 QTAILQ_REMOVE(&obj->properties, prop, node);
315
316 if (prop->release) {
317 prop->release(obj, prop->name, prop->opaque);
318 }
319
320 g_free(prop->name);
321 g_free(prop->type);
322 g_free(prop);
323 }
324 }
325
326 static void object_property_del_child(Object *obj, Object *child, Error **errp)
327 {
328 ObjectProperty *prop;
329
330 QTAILQ_FOREACH(prop, &obj->properties, node) {
331 if (object_property_is_child(prop) && prop->opaque == child) {
332 object_property_del(obj, prop->name, errp);
333 break;
334 }
335 }
336 }
337
338 void object_unparent(Object *obj)
339 {
340 if (obj->parent) {
341 object_property_del_child(obj->parent, obj, NULL);
342 }
343 }
344
345 static void object_deinit(Object *obj, TypeImpl *type)
346 {
347 if (type->instance_finalize) {
348 type->instance_finalize(obj);
349 }
350
351 while (obj->interfaces) {
352 Interface *iface_obj = obj->interfaces->data;
353 obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
354 object_delete(OBJECT(iface_obj));
355 }
356
357 if (type_has_parent(type)) {
358 object_deinit(obj, type_get_parent(type));
359 }
360
361 object_unparent(obj);
362 }
363
364 void object_finalize(void *data)
365 {
366 Object *obj = data;
367 TypeImpl *ti = obj->class->type;
368
369 object_deinit(obj, ti);
370 object_property_del_all(obj);
371
372 g_assert(obj->ref == 0);
373 }
374
375 Object *object_new_with_type(Type type)
376 {
377 Object *obj;
378
379 g_assert(type != NULL);
380 type_initialize(type);
381
382 obj = g_malloc(type->instance_size);
383 object_initialize_with_type(obj, type);
384 object_ref(obj);
385
386 return obj;
387 }
388
389 Object *object_new(const char *typename)
390 {
391 TypeImpl *ti = type_get_by_name(typename);
392
393 return object_new_with_type(ti);
394 }
395
396 void object_delete(Object *obj)
397 {
398 object_unref(obj);
399 g_assert(obj->ref == 0);
400 g_free(obj);
401 }
402
403 static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
404 {
405 assert(target_type);
406
407 /* Check if typename is a direct ancestor of type */
408 while (type) {
409 if (type == target_type) {
410 return true;
411 }
412
413 type = type_get_parent(type);
414 }
415
416 return false;
417 }
418
419 static bool object_is_type(Object *obj, TypeImpl *target_type)
420 {
421 return !target_type || type_is_ancestor(obj->class->type, target_type);
422 }
423
424 Object *object_dynamic_cast(Object *obj, const char *typename)
425 {
426 TypeImpl *target_type = type_get_by_name(typename);
427 GSList *i;
428
429 /* Check if typename is a direct ancestor. Special-case TYPE_OBJECT,
430 * we want to go back from interfaces to the parent.
431 */
432 if (target_type && object_is_type(obj, target_type)) {
433 return obj;
434 }
435
436 /* Check if obj is an interface and its containing object is a direct
437 * ancestor of typename. In principle we could do this test at the very
438 * beginning of object_dynamic_cast, avoiding a second call to
439 * object_is_type. However, casting between interfaces is relatively
440 * rare, and object_is_type(obj, type_interface) would fail almost always.
441 *
442 * Perhaps we could add a magic value to the object header for increased
443 * (run-time) type safety and to speed up tests like this one. If we ever
444 * do that we can revisit the order here.
445 */
446 if (object_is_type(obj, type_interface)) {
447 assert(!obj->interfaces);
448 obj = INTERFACE(obj)->obj;
449 if (object_is_type(obj, target_type)) {
450 return obj;
451 }
452 }
453
454 if (!target_type) {
455 return obj;
456 }
457
458 /* Check if obj has an interface of typename */
459 for (i = obj->interfaces; i; i = i->next) {
460 Interface *iface = i->data;
461
462 if (object_is_type(OBJECT(iface), target_type)) {
463 return OBJECT(iface);
464 }
465 }
466
467 return NULL;
468 }
469
470
471 static void register_types(void)
472 {
473 static TypeInfo interface_info = {
474 .name = TYPE_INTERFACE,
475 .instance_size = sizeof(Interface),
476 .abstract = true,
477 };
478
479 type_interface = type_register_static(&interface_info);
480 }
481
482 type_init(register_types)
483
484 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
485 {
486 Object *inst;
487
488 inst = object_dynamic_cast(obj, typename);
489
490 if (!inst) {
491 fprintf(stderr, "Object %p is not an instance of type %s\n",
492 obj, typename);
493 abort();
494 }
495
496 return inst;
497 }
498
499 ObjectClass *object_class_dynamic_cast(ObjectClass *class,
500 const char *typename)
501 {
502 TypeImpl *target_type = type_get_by_name(typename);
503 TypeImpl *type = class->type;
504
505 while (type) {
506 if (type == target_type) {
507 return class;
508 }
509
510 type = type_get_parent(type);
511 }
512
513 return NULL;
514 }
515
516 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
517 const char *typename)
518 {
519 ObjectClass *ret = object_class_dynamic_cast(class, typename);
520
521 if (!ret) {
522 fprintf(stderr, "Object %p is not an instance of type %s\n",
523 class, typename);
524 abort();
525 }
526
527 return ret;
528 }
529
530 const char *object_get_typename(Object *obj)
531 {
532 return obj->class->type->name;
533 }
534
535 ObjectClass *object_get_class(Object *obj)
536 {
537 return obj->class;
538 }
539
540 const char *object_class_get_name(ObjectClass *klass)
541 {
542 return klass->type->name;
543 }
544
545 ObjectClass *object_class_by_name(const char *typename)
546 {
547 TypeImpl *type = type_get_by_name(typename);
548
549 if (!type) {
550 return NULL;
551 }
552
553 type_initialize(type);
554
555 return type->class;
556 }
557
558 ObjectClass *object_class_get_parent(ObjectClass *class)
559 {
560 TypeImpl *type = type_get_parent(class->type);
561
562 if (!type) {
563 return NULL;
564 }
565
566 type_initialize(type);
567
568 return type->class;
569 }
570
571 typedef struct OCFData
572 {
573 void (*fn)(ObjectClass *klass, void *opaque);
574 const char *implements_type;
575 bool include_abstract;
576 void *opaque;
577 } OCFData;
578
579 static void object_class_foreach_tramp(gpointer key, gpointer value,
580 gpointer opaque)
581 {
582 OCFData *data = opaque;
583 TypeImpl *type = value;
584 ObjectClass *k;
585
586 type_initialize(type);
587 k = type->class;
588
589 if (!data->include_abstract && type->abstract) {
590 return;
591 }
592
593 if (data->implements_type &&
594 !object_class_dynamic_cast(k, data->implements_type)) {
595 return;
596 }
597
598 data->fn(k, data->opaque);
599 }
600
601 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
602 const char *implements_type, bool include_abstract,
603 void *opaque)
604 {
605 OCFData data = { fn, implements_type, include_abstract, opaque };
606
607 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
608 }
609
610 static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
611 {
612 GSList **list = opaque;
613
614 *list = g_slist_prepend(*list, klass);
615 }
616
617 GSList *object_class_get_list(const char *implements_type,
618 bool include_abstract)
619 {
620 GSList *list = NULL;
621
622 object_class_foreach(object_class_get_list_tramp,
623 implements_type, include_abstract, &list);
624 return list;
625 }
626
627 void object_ref(Object *obj)
628 {
629 obj->ref++;
630 }
631
632 void object_unref(Object *obj)
633 {
634 g_assert(obj->ref > 0);
635 obj->ref--;
636
637 /* parent always holds a reference to its children */
638 if (obj->ref == 0) {
639 object_finalize(obj);
640 }
641 }
642
643 void object_property_add(Object *obj, const char *name, const char *type,
644 ObjectPropertyAccessor *get,
645 ObjectPropertyAccessor *set,
646 ObjectPropertyRelease *release,
647 void *opaque, Error **errp)
648 {
649 ObjectProperty *prop = g_malloc0(sizeof(*prop));
650
651 prop->name = g_strdup(name);
652 prop->type = g_strdup(type);
653
654 prop->get = get;
655 prop->set = set;
656 prop->release = release;
657 prop->opaque = opaque;
658
659 QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
660 }
661
662 static ObjectProperty *object_property_find(Object *obj, const char *name)
663 {
664 ObjectProperty *prop;
665
666 QTAILQ_FOREACH(prop, &obj->properties, node) {
667 if (strcmp(prop->name, name) == 0) {
668 return prop;
669 }
670 }
671
672 return NULL;
673 }
674
675 void object_property_del(Object *obj, const char *name, Error **errp)
676 {
677 ObjectProperty *prop = object_property_find(obj, name);
678
679 QTAILQ_REMOVE(&obj->properties, prop, node);
680
681 prop->release(obj, prop->name, prop->opaque);
682
683 g_free(prop->name);
684 g_free(prop->type);
685 g_free(prop);
686 }
687
688 void object_property_get(Object *obj, Visitor *v, const char *name,
689 Error **errp)
690 {
691 ObjectProperty *prop = object_property_find(obj, name);
692
693 if (prop == NULL) {
694 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
695 return;
696 }
697
698 if (!prop->get) {
699 error_set(errp, QERR_PERMISSION_DENIED);
700 } else {
701 prop->get(obj, v, prop->opaque, name, errp);
702 }
703 }
704
705 void object_property_set(Object *obj, Visitor *v, const char *name,
706 Error **errp)
707 {
708 ObjectProperty *prop = object_property_find(obj, name);
709
710 if (prop == NULL) {
711 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
712 return;
713 }
714
715 if (!prop->set) {
716 error_set(errp, QERR_PERMISSION_DENIED);
717 } else {
718 prop->set(obj, v, prop->opaque, name, errp);
719 }
720 }
721
722 void object_property_set_str(Object *obj, const char *value,
723 const char *name, Error **errp)
724 {
725 QString *qstr = qstring_from_str(value);
726 object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
727
728 QDECREF(qstr);
729 }
730
731 char *object_property_get_str(Object *obj, const char *name,
732 Error **errp)
733 {
734 QObject *ret = object_property_get_qobject(obj, name, errp);
735 QString *qstring;
736 char *retval;
737
738 if (!ret) {
739 return NULL;
740 }
741 qstring = qobject_to_qstring(ret);
742 if (!qstring) {
743 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
744 retval = NULL;
745 } else {
746 retval = g_strdup(qstring_get_str(qstring));
747 }
748
749 QDECREF(qstring);
750 return retval;
751 }
752
753 void object_property_set_link(Object *obj, Object *value,
754 const char *name, Error **errp)
755 {
756 object_property_set_str(obj, object_get_canonical_path(value),
757 name, errp);
758 }
759
760 Object *object_property_get_link(Object *obj, const char *name,
761 Error **errp)
762 {
763 char *str = object_property_get_str(obj, name, errp);
764 Object *target = NULL;
765
766 if (str && *str) {
767 target = object_resolve_path(str, NULL);
768 if (!target) {
769 error_set(errp, QERR_DEVICE_NOT_FOUND, str);
770 }
771 }
772
773 g_free(str);
774 return target;
775 }
776
777 void object_property_set_bool(Object *obj, bool value,
778 const char *name, Error **errp)
779 {
780 QBool *qbool = qbool_from_int(value);
781 object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
782
783 QDECREF(qbool);
784 }
785
786 bool object_property_get_bool(Object *obj, const char *name,
787 Error **errp)
788 {
789 QObject *ret = object_property_get_qobject(obj, name, errp);
790 QBool *qbool;
791 bool retval;
792
793 if (!ret) {
794 return false;
795 }
796 qbool = qobject_to_qbool(ret);
797 if (!qbool) {
798 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
799 retval = false;
800 } else {
801 retval = qbool_get_int(qbool);
802 }
803
804 QDECREF(qbool);
805 return retval;
806 }
807
808 void object_property_set_int(Object *obj, int64_t value,
809 const char *name, Error **errp)
810 {
811 QInt *qint = qint_from_int(value);
812 object_property_set_qobject(obj, QOBJECT(qint), name, errp);
813
814 QDECREF(qint);
815 }
816
817 int64_t object_property_get_int(Object *obj, const char *name,
818 Error **errp)
819 {
820 QObject *ret = object_property_get_qobject(obj, name, errp);
821 QInt *qint;
822 int64_t retval;
823
824 if (!ret) {
825 return -1;
826 }
827 qint = qobject_to_qint(ret);
828 if (!qint) {
829 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
830 retval = -1;
831 } else {
832 retval = qint_get_int(qint);
833 }
834
835 QDECREF(qint);
836 return retval;
837 }
838
839 void object_property_parse(Object *obj, const char *string,
840 const char *name, Error **errp)
841 {
842 StringInputVisitor *mi;
843 mi = string_input_visitor_new(string);
844 object_property_set(obj, string_input_get_visitor(mi), name, errp);
845
846 string_input_visitor_cleanup(mi);
847 }
848
849 char *object_property_print(Object *obj, const char *name,
850 Error **errp)
851 {
852 StringOutputVisitor *mo;
853 char *string;
854
855 mo = string_output_visitor_new();
856 object_property_get(obj, string_output_get_visitor(mo), name, errp);
857 string = string_output_get_string(mo);
858 string_output_visitor_cleanup(mo);
859 return string;
860 }
861
862 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
863 {
864 ObjectProperty *prop = object_property_find(obj, name);
865
866 if (prop == NULL) {
867 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
868 return NULL;
869 }
870
871 return prop->type;
872 }
873
874 Object *object_get_root(void)
875 {
876 static Object *root;
877
878 if (!root) {
879 root = object_new("container");
880 }
881
882 return root;
883 }
884
885 static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
886 const char *name, Error **errp)
887 {
888 Object *child = opaque;
889 gchar *path;
890
891 path = object_get_canonical_path(child);
892 visit_type_str(v, &path, name, errp);
893 g_free(path);
894 }
895
896 static void object_finalize_child_property(Object *obj, const char *name,
897 void *opaque)
898 {
899 Object *child = opaque;
900
901 object_unref(child);
902 }
903
904 void object_property_add_child(Object *obj, const char *name,
905 Object *child, Error **errp)
906 {
907 gchar *type;
908
909 /* Registering an interface object in the composition tree will mightily
910 * confuse object_get_canonical_path (which, on the other hand, knows how
911 * to get the canonical path of an interface object).
912 */
913 assert(!object_is_type(obj, type_interface));
914
915 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
916
917 object_property_add(obj, name, type, object_get_child_property,
918 NULL, object_finalize_child_property, child, errp);
919
920 object_ref(child);
921 g_assert(child->parent == NULL);
922 child->parent = obj;
923
924 g_free(type);
925 }
926
927 static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
928 const char *name, Error **errp)
929 {
930 Object **child = opaque;
931 gchar *path;
932
933 if (*child) {
934 path = object_get_canonical_path(*child);
935 visit_type_str(v, &path, name, errp);
936 g_free(path);
937 } else {
938 path = (gchar *)"";
939 visit_type_str(v, &path, name, errp);
940 }
941 }
942
943 static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
944 const char *name, Error **errp)
945 {
946 Object **child = opaque;
947 Object *old_target;
948 bool ambiguous = false;
949 const char *type;
950 char *path;
951 gchar *target_type;
952
953 type = object_property_get_type(obj, name, NULL);
954
955 visit_type_str(v, &path, name, errp);
956
957 old_target = *child;
958 *child = NULL;
959
960 if (strcmp(path, "") != 0) {
961 Object *target;
962
963 /* Go from link<FOO> to FOO. */
964 target_type = g_strndup(&type[5], strlen(type) - 6);
965 target = object_resolve_path_type(path, target_type, &ambiguous);
966
967 if (ambiguous) {
968 error_set(errp, QERR_AMBIGUOUS_PATH, path);
969 } else if (target) {
970 object_ref(target);
971 *child = target;
972 } else {
973 target = object_resolve_path(path, &ambiguous);
974 if (target || ambiguous) {
975 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
976 } else {
977 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
978 }
979 }
980 g_free(target_type);
981 }
982
983 g_free(path);
984
985 if (old_target != NULL) {
986 object_unref(old_target);
987 }
988 }
989
990 void object_property_add_link(Object *obj, const char *name,
991 const char *type, Object **child,
992 Error **errp)
993 {
994 gchar *full_type;
995
996 full_type = g_strdup_printf("link<%s>", type);
997
998 object_property_add(obj, name, full_type,
999 object_get_link_property,
1000 object_set_link_property,
1001 NULL, child, errp);
1002
1003 g_free(full_type);
1004 }
1005
1006 gchar *object_get_canonical_path(Object *obj)
1007 {
1008 Object *root = object_get_root();
1009 char *newpath = NULL, *path = NULL;
1010
1011 if (object_is_type(obj, type_interface)) {
1012 obj = INTERFACE(obj)->obj;
1013 }
1014
1015 while (obj != root) {
1016 ObjectProperty *prop = NULL;
1017
1018 g_assert(obj->parent != NULL);
1019
1020 QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
1021 if (!object_property_is_child(prop)) {
1022 continue;
1023 }
1024
1025 if (prop->opaque == obj) {
1026 if (path) {
1027 newpath = g_strdup_printf("%s/%s", prop->name, path);
1028 g_free(path);
1029 path = newpath;
1030 } else {
1031 path = g_strdup(prop->name);
1032 }
1033 break;
1034 }
1035 }
1036
1037 g_assert(prop != NULL);
1038
1039 obj = obj->parent;
1040 }
1041
1042 newpath = g_strdup_printf("/%s", path);
1043 g_free(path);
1044
1045 return newpath;
1046 }
1047
1048 Object *object_resolve_path_component(Object *parent, gchar *part)
1049 {
1050 ObjectProperty *prop = object_property_find(parent, part);
1051 if (prop == NULL) {
1052 return NULL;
1053 }
1054
1055 if (object_property_is_link(prop)) {
1056 return *(Object **)prop->opaque;
1057 } else if (object_property_is_child(prop)) {
1058 return prop->opaque;
1059 } else {
1060 return NULL;
1061 }
1062 }
1063
1064 static Object *object_resolve_abs_path(Object *parent,
1065 gchar **parts,
1066 const char *typename,
1067 int index)
1068 {
1069 Object *child;
1070
1071 if (parts[index] == NULL) {
1072 return object_dynamic_cast(parent, typename);
1073 }
1074
1075 if (strcmp(parts[index], "") == 0) {
1076 return object_resolve_abs_path(parent, parts, typename, index + 1);
1077 }
1078
1079 child = object_resolve_path_component(parent, parts[index]);
1080 if (!child) {
1081 return NULL;
1082 }
1083
1084 return object_resolve_abs_path(child, parts, typename, index + 1);
1085 }
1086
1087 static Object *object_resolve_partial_path(Object *parent,
1088 gchar **parts,
1089 const char *typename,
1090 bool *ambiguous)
1091 {
1092 Object *obj;
1093 ObjectProperty *prop;
1094
1095 obj = object_resolve_abs_path(parent, parts, typename, 0);
1096
1097 QTAILQ_FOREACH(prop, &parent->properties, node) {
1098 Object *found;
1099
1100 if (!object_property_is_child(prop)) {
1101 continue;
1102 }
1103
1104 found = object_resolve_partial_path(prop->opaque, parts,
1105 typename, ambiguous);
1106 if (found) {
1107 if (obj) {
1108 if (ambiguous) {
1109 *ambiguous = true;
1110 }
1111 return NULL;
1112 }
1113 obj = found;
1114 }
1115
1116 if (ambiguous && *ambiguous) {
1117 return NULL;
1118 }
1119 }
1120
1121 return obj;
1122 }
1123
1124 Object *object_resolve_path_type(const char *path, const char *typename,
1125 bool *ambiguous)
1126 {
1127 bool partial_path = true;
1128 Object *obj;
1129 gchar **parts;
1130
1131 parts = g_strsplit(path, "/", 0);
1132 if (parts == NULL || parts[0] == NULL) {
1133 g_strfreev(parts);
1134 return object_get_root();
1135 }
1136
1137 if (strcmp(parts[0], "") == 0) {
1138 partial_path = false;
1139 }
1140
1141 if (partial_path) {
1142 if (ambiguous) {
1143 *ambiguous = false;
1144 }
1145 obj = object_resolve_partial_path(object_get_root(), parts,
1146 typename, ambiguous);
1147 } else {
1148 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1149 }
1150
1151 g_strfreev(parts);
1152
1153 return obj;
1154 }
1155
1156 Object *object_resolve_path(const char *path, bool *ambiguous)
1157 {
1158 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1159 }
1160
1161 typedef struct StringProperty
1162 {
1163 char *(*get)(Object *, Error **);
1164 void (*set)(Object *, const char *, Error **);
1165 } StringProperty;
1166
1167 static void property_get_str(Object *obj, Visitor *v, void *opaque,
1168 const char *name, Error **errp)
1169 {
1170 StringProperty *prop = opaque;
1171 char *value;
1172
1173 value = prop->get(obj, errp);
1174 if (value) {
1175 visit_type_str(v, &value, name, errp);
1176 g_free(value);
1177 }
1178 }
1179
1180 static void property_set_str(Object *obj, Visitor *v, void *opaque,
1181 const char *name, Error **errp)
1182 {
1183 StringProperty *prop = opaque;
1184 char *value;
1185 Error *local_err = NULL;
1186
1187 visit_type_str(v, &value, name, &local_err);
1188 if (local_err) {
1189 error_propagate(errp, local_err);
1190 return;
1191 }
1192
1193 prop->set(obj, value, errp);
1194 g_free(value);
1195 }
1196
1197 static void property_release_str(Object *obj, const char *name,
1198 void *opaque)
1199 {
1200 StringProperty *prop = opaque;
1201 g_free(prop);
1202 }
1203
1204 void object_property_add_str(Object *obj, const char *name,
1205 char *(*get)(Object *, Error **),
1206 void (*set)(Object *, const char *, Error **),
1207 Error **errp)
1208 {
1209 StringProperty *prop = g_malloc0(sizeof(*prop));
1210
1211 prop->get = get;
1212 prop->set = set;
1213
1214 object_property_add(obj, name, "string",
1215 get ? property_get_str : NULL,
1216 set ? property_set_str : NULL,
1217 property_release_str,
1218 prop, errp);
1219 }