]> git.proxmox.com Git - mirror_qemu.git/blob - qom/object.c
qom: clean up/optimize object_dynamic_cast
[mirror_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 "hw/qdev.h"
17 // FIXME remove above
18
19 #define MAX_INTERFACES 32
20
21 typedef struct InterfaceImpl InterfaceImpl;
22 typedef struct TypeImpl TypeImpl;
23
24 struct InterfaceImpl
25 {
26 const char *parent;
27 void (*interface_initfn)(ObjectClass *class, void *data);
28 TypeImpl *type;
29 };
30
31 struct TypeImpl
32 {
33 const char *name;
34
35 size_t class_size;
36
37 size_t instance_size;
38
39 void (*class_init)(ObjectClass *klass, void *data);
40 void (*class_finalize)(ObjectClass *klass, void *data);
41
42 void *class_data;
43
44 void (*instance_init)(Object *obj);
45 void (*instance_finalize)(Object *obj);
46
47 bool abstract;
48
49 const char *parent;
50 TypeImpl *parent_type;
51
52 ObjectClass *class;
53
54 int num_interfaces;
55 InterfaceImpl interfaces[MAX_INTERFACES];
56 };
57
58 typedef struct Interface
59 {
60 Object parent;
61 Object *obj;
62 } Interface;
63
64 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
65
66 static GHashTable *type_table_get(void)
67 {
68 static GHashTable *type_table;
69
70 if (type_table == NULL) {
71 type_table = g_hash_table_new(g_str_hash, g_str_equal);
72 }
73
74 return type_table;
75 }
76
77 static void type_table_add(TypeImpl *ti)
78 {
79 g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
80 }
81
82 static TypeImpl *type_table_lookup(const char *name)
83 {
84 return g_hash_table_lookup(type_table_get(), name);
85 }
86
87 TypeImpl *type_register(const TypeInfo *info)
88 {
89 TypeImpl *ti = g_malloc0(sizeof(*ti));
90
91 g_assert(info->name != NULL);
92
93 if (type_table_lookup(info->name) != NULL) {
94 fprintf(stderr, "Registering `%s' which already exists\n", info->name);
95 abort();
96 }
97
98 ti->name = g_strdup(info->name);
99 ti->parent = g_strdup(info->parent);
100
101 ti->class_size = info->class_size;
102 ti->instance_size = info->instance_size;
103
104 ti->class_init = info->class_init;
105 ti->class_finalize = info->class_finalize;
106 ti->class_data = info->class_data;
107
108 ti->instance_init = info->instance_init;
109 ti->instance_finalize = info->instance_finalize;
110
111 ti->abstract = info->abstract;
112
113 if (info->interfaces) {
114 int i;
115
116 for (i = 0; info->interfaces[i].type; i++) {
117 ti->interfaces[i].parent = info->interfaces[i].type;
118 ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
119 ti->num_interfaces++;
120 }
121 }
122
123 type_table_add(ti);
124
125 return ti;
126 }
127
128 TypeImpl *type_register_static(const TypeInfo *info)
129 {
130 return type_register(info);
131 }
132
133 static TypeImpl *type_get_by_name(const char *name)
134 {
135 if (name == NULL) {
136 return NULL;
137 }
138
139 return type_table_lookup(name);
140 }
141
142 static TypeImpl *type_get_parent(TypeImpl *type)
143 {
144 if (!type->parent_type && type->parent) {
145 type->parent_type = type_get_by_name(type->parent);
146 g_assert(type->parent_type != NULL);
147 }
148
149 return type->parent_type;
150 }
151
152 static bool type_has_parent(TypeImpl *type)
153 {
154 return (type->parent != NULL);
155 }
156
157 static size_t type_class_get_size(TypeImpl *ti)
158 {
159 if (ti->class_size) {
160 return ti->class_size;
161 }
162
163 if (type_has_parent(ti)) {
164 return type_class_get_size(type_get_parent(ti));
165 }
166
167 return sizeof(ObjectClass);
168 }
169
170 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
171 {
172 TypeInfo info = {
173 .instance_size = sizeof(Interface),
174 .parent = iface->parent,
175 .class_size = sizeof(InterfaceClass),
176 .class_init = iface->interface_initfn,
177 .abstract = true,
178 };
179 char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
180
181 info.name = name;
182 iface->type = type_register(&info);
183 g_free(name);
184 }
185
186 static void type_class_init(TypeImpl *ti)
187 {
188 size_t class_size = sizeof(ObjectClass);
189 int i;
190
191 if (ti->class) {
192 return;
193 }
194
195 ti->class_size = type_class_get_size(ti);
196
197 ti->class = g_malloc0(ti->class_size);
198 ti->class->type = ti;
199
200 if (type_has_parent(ti)) {
201 TypeImpl *parent = type_get_parent(ti);
202
203 type_class_init(parent);
204
205 class_size = parent->class_size;
206 g_assert(parent->class_size <= ti->class_size);
207
208 memcpy((void *)ti->class + sizeof(ObjectClass),
209 (void *)parent->class + sizeof(ObjectClass),
210 parent->class_size - sizeof(ObjectClass));
211 }
212
213 memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
214
215 for (i = 0; i < ti->num_interfaces; i++) {
216 type_class_interface_init(ti, &ti->interfaces[i]);
217 }
218
219 if (ti->class_init) {
220 ti->class_init(ti->class, ti->class_data);
221 }
222 }
223
224 static void object_interface_init(Object *obj, InterfaceImpl *iface)
225 {
226 TypeImpl *ti = iface->type;
227 Interface *iface_obj;
228
229 iface_obj = INTERFACE(object_new(ti->name));
230 iface_obj->obj = obj;
231
232 obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
233 }
234
235 static void object_init_with_type(Object *obj, TypeImpl *ti)
236 {
237 int i;
238
239 if (type_has_parent(ti)) {
240 object_init_with_type(obj, type_get_parent(ti));
241 }
242
243 for (i = 0; i < ti->num_interfaces; i++) {
244 object_interface_init(obj, &ti->interfaces[i]);
245 }
246
247 if (ti->instance_init) {
248 ti->instance_init(obj);
249 }
250 }
251
252 void object_initialize_with_type(void *data, TypeImpl *type)
253 {
254 Object *obj = data;
255
256 g_assert(type != NULL);
257 g_assert(type->instance_size >= sizeof(ObjectClass));
258
259 type_class_init(type);
260 g_assert(type->abstract == false);
261
262 memset(obj, 0, type->instance_size);
263 obj->class = type->class;
264 QTAILQ_INIT(&obj->properties);
265 object_init_with_type(obj, type);
266 }
267
268 void object_initialize(void *data, const char *typename)
269 {
270 TypeImpl *type = type_get_by_name(typename);
271
272 object_initialize_with_type(data, type);
273 }
274
275 static void object_property_del_all(Object *obj)
276 {
277 while (!QTAILQ_EMPTY(&obj->properties)) {
278 ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
279
280 QTAILQ_REMOVE(&obj->properties, prop, node);
281
282 if (prop->release) {
283 prop->release(obj, prop->name, prop->opaque);
284 }
285
286 g_free(prop->name);
287 g_free(prop->type);
288 g_free(prop);
289 }
290 }
291
292 static void object_property_del_child(Object *obj, Object *child, Error **errp)
293 {
294 ObjectProperty *prop;
295
296 QTAILQ_FOREACH(prop, &obj->properties, node) {
297 if (!strstart(prop->type, "child<", NULL)) {
298 continue;
299 }
300
301 if (prop->opaque == child) {
302 object_property_del(obj, prop->name, errp);
303 }
304 }
305 }
306
307 void object_unparent(Object *obj)
308 {
309 if (obj->parent) {
310 object_property_del_child(obj->parent, obj, NULL);
311 }
312 }
313
314 static void object_deinit(Object *obj, TypeImpl *type)
315 {
316 if (type->instance_finalize) {
317 type->instance_finalize(obj);
318 }
319
320 while (obj->interfaces) {
321 Interface *iface_obj = obj->interfaces->data;
322 obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
323 object_delete(OBJECT(iface_obj));
324 }
325
326 if (type_has_parent(type)) {
327 object_deinit(obj, type_get_parent(type));
328 }
329
330 object_unparent(obj);
331 }
332
333 void object_finalize(void *data)
334 {
335 Object *obj = data;
336 TypeImpl *ti = obj->class->type;
337
338 object_deinit(obj, ti);
339 object_property_del_all(obj);
340
341 g_assert(obj->ref == 0);
342 }
343
344 Object *object_new_with_type(Type type)
345 {
346 Object *obj;
347
348 g_assert(type != NULL);
349
350 obj = g_malloc(type->instance_size);
351 object_initialize_with_type(obj, type);
352 object_ref(obj);
353
354 return obj;
355 }
356
357 Object *object_new(const char *typename)
358 {
359 TypeImpl *ti = type_get_by_name(typename);
360
361 return object_new_with_type(ti);
362 }
363
364 void object_delete(Object *obj)
365 {
366 object_unref(obj);
367 g_assert(obj->ref == 0);
368 g_free(obj);
369 }
370
371 static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
372 {
373 assert(target_type);
374
375 /* Check if typename is a direct ancestor of type */
376 while (type) {
377 if (type == target_type) {
378 return true;
379 }
380
381 type = type_get_parent(type);
382 }
383
384 return false;
385 }
386
387 static bool object_is_type(Object *obj, const char *typename)
388 {
389 TypeImpl *target_type;
390
391 if (typename == TYPE_OBJECT) {
392 return true;
393 }
394 target_type = type_get_by_name(typename);
395 return type_is_ancestor(obj->class->type, target_type);
396 }
397
398 Object *object_dynamic_cast(Object *obj, const char *typename)
399 {
400 GSList *i;
401
402 /* Check if typename is a direct ancestor. Special-case TYPE_OBJECT,
403 * we want to go back from interfaces to the parent.
404 */
405 if (typename && object_is_type(obj, typename)) {
406 return obj;
407 }
408
409 /* Check if obj is an interface and its containing object is a direct
410 * ancestor of typename. In principle we could do this test at the very
411 * beginning of object_dynamic_cast, avoiding a second call to
412 * object_is_type. However, casting between interfaces is relatively
413 * rare, and object_is_type(obj, TYPE_INTERFACE) would fail almost always.
414 *
415 * Perhaps we could add a magic value to the object header for increased
416 * (run-time) type safety and to speed up tests like this one. If we ever
417 * do that we can revisit the order here.
418 */
419 if (object_is_type(obj, TYPE_INTERFACE)) {
420 assert(!obj->interfaces);
421 obj = INTERFACE(obj)->obj;
422 if (object_is_type(obj, typename)) {
423 return obj;
424 }
425 }
426
427 if (typename == TYPE_OBJECT) {
428 return obj;
429 }
430
431 /* Check if obj has an interface of typename */
432 for (i = obj->interfaces; i; i = i->next) {
433 Interface *iface = i->data;
434
435 if (object_is_type(OBJECT(iface), typename)) {
436 return OBJECT(iface);
437 }
438 }
439
440 return NULL;
441 }
442
443
444 static void register_interface(void)
445 {
446 static TypeInfo interface_info = {
447 .name = TYPE_INTERFACE,
448 .instance_size = sizeof(Interface),
449 .abstract = true,
450 };
451
452 type_register_static(&interface_info);
453 }
454
455 device_init(register_interface);
456
457 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
458 {
459 Object *inst;
460
461 inst = object_dynamic_cast(obj, typename);
462
463 if (!inst) {
464 fprintf(stderr, "Object %p is not an instance of type %s\n",
465 obj, typename);
466 abort();
467 }
468
469 return inst;
470 }
471
472 ObjectClass *object_class_dynamic_cast(ObjectClass *class,
473 const char *typename)
474 {
475 TypeImpl *target_type = type_get_by_name(typename);
476 TypeImpl *type = class->type;
477
478 while (type) {
479 if (type == target_type) {
480 return class;
481 }
482
483 type = type_get_parent(type);
484 }
485
486 return NULL;
487 }
488
489 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
490 const char *typename)
491 {
492 ObjectClass *ret = object_class_dynamic_cast(class, typename);
493
494 if (!ret) {
495 fprintf(stderr, "Object %p is not an instance of type %s\n",
496 class, typename);
497 abort();
498 }
499
500 return ret;
501 }
502
503 const char *object_get_typename(Object *obj)
504 {
505 return obj->class->type->name;
506 }
507
508 ObjectClass *object_get_class(Object *obj)
509 {
510 return obj->class;
511 }
512
513 const char *object_class_get_name(ObjectClass *klass)
514 {
515 return klass->type->name;
516 }
517
518 ObjectClass *object_class_by_name(const char *typename)
519 {
520 TypeImpl *type = type_get_by_name(typename);
521
522 if (!type) {
523 return NULL;
524 }
525
526 type_class_init(type);
527
528 return type->class;
529 }
530
531 typedef struct OCFData
532 {
533 void (*fn)(ObjectClass *klass, void *opaque);
534 const char *implements_type;
535 bool include_abstract;
536 void *opaque;
537 } OCFData;
538
539 static void object_class_foreach_tramp(gpointer key, gpointer value,
540 gpointer opaque)
541 {
542 OCFData *data = opaque;
543 TypeImpl *type = value;
544 ObjectClass *k;
545
546 type_class_init(type);
547 k = type->class;
548
549 if (!data->include_abstract && type->abstract) {
550 return;
551 }
552
553 if (data->implements_type &&
554 !object_class_dynamic_cast(k, data->implements_type)) {
555 return;
556 }
557
558 data->fn(k, data->opaque);
559 }
560
561 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
562 const char *implements_type, bool include_abstract,
563 void *opaque)
564 {
565 OCFData data = { fn, implements_type, include_abstract, opaque };
566
567 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
568 }
569
570 void object_ref(Object *obj)
571 {
572 obj->ref++;
573 }
574
575 void object_unref(Object *obj)
576 {
577 g_assert(obj->ref > 0);
578 obj->ref--;
579
580 /* parent always holds a reference to its children */
581 if (obj->ref == 0) {
582 object_finalize(obj);
583 }
584 }
585
586 void object_property_add(Object *obj, const char *name, const char *type,
587 ObjectPropertyAccessor *get,
588 ObjectPropertyAccessor *set,
589 ObjectPropertyRelease *release,
590 void *opaque, Error **errp)
591 {
592 ObjectProperty *prop = g_malloc0(sizeof(*prop));
593
594 prop->name = g_strdup(name);
595 prop->type = g_strdup(type);
596
597 prop->get = get;
598 prop->set = set;
599 prop->release = release;
600 prop->opaque = opaque;
601
602 QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
603 }
604
605 static ObjectProperty *object_property_find(Object *obj, const char *name)
606 {
607 ObjectProperty *prop;
608
609 QTAILQ_FOREACH(prop, &obj->properties, node) {
610 if (strcmp(prop->name, name) == 0) {
611 return prop;
612 }
613 }
614
615 return NULL;
616 }
617
618 void object_property_del(Object *obj, const char *name, Error **errp)
619 {
620 ObjectProperty *prop = object_property_find(obj, name);
621
622 QTAILQ_REMOVE(&obj->properties, prop, node);
623
624 prop->release(obj, prop->name, prop->opaque);
625
626 g_free(prop->name);
627 g_free(prop->type);
628 g_free(prop);
629 }
630
631 void object_property_get(Object *obj, Visitor *v, const char *name,
632 Error **errp)
633 {
634 ObjectProperty *prop = object_property_find(obj, name);
635
636 if (prop == NULL) {
637 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
638 return;
639 }
640
641 if (!prop->get) {
642 error_set(errp, QERR_PERMISSION_DENIED);
643 } else {
644 prop->get(obj, v, prop->opaque, name, errp);
645 }
646 }
647
648 void object_property_set(Object *obj, Visitor *v, const char *name,
649 Error **errp)
650 {
651 ObjectProperty *prop = object_property_find(obj, name);
652
653 if (prop == NULL) {
654 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
655 return;
656 }
657
658 if (!prop->set) {
659 error_set(errp, QERR_PERMISSION_DENIED);
660 } else {
661 prop->set(obj, v, prop->opaque, name, errp);
662 }
663 }
664
665 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
666 {
667 ObjectProperty *prop = object_property_find(obj, name);
668
669 if (prop == NULL) {
670 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
671 return NULL;
672 }
673
674 return prop->type;
675 }
676
677 Object *object_get_root(void)
678 {
679 static Object *root;
680
681 if (!root) {
682 root = object_new("container");
683 }
684
685 return root;
686 }
687
688 static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
689 const char *name, Error **errp)
690 {
691 Object *child = opaque;
692 gchar *path;
693
694 path = object_get_canonical_path(child);
695 visit_type_str(v, &path, name, errp);
696 g_free(path);
697 }
698
699 static void object_finalize_child_property(Object *obj, const char *name,
700 void *opaque)
701 {
702 Object *child = opaque;
703
704 object_unref(child);
705 }
706
707 void object_property_add_child(Object *obj, const char *name,
708 Object *child, Error **errp)
709 {
710 gchar *type;
711
712 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
713
714 object_property_add(obj, name, type, object_get_child_property,
715 NULL, object_finalize_child_property, child, errp);
716
717 object_ref(child);
718 g_assert(child->parent == NULL);
719 child->parent = obj;
720
721 g_free(type);
722 }
723
724 static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
725 const char *name, Error **errp)
726 {
727 Object **child = opaque;
728 gchar *path;
729
730 if (*child) {
731 path = object_get_canonical_path(*child);
732 visit_type_str(v, &path, name, errp);
733 g_free(path);
734 } else {
735 path = (gchar *)"";
736 visit_type_str(v, &path, name, errp);
737 }
738 }
739
740 static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
741 const char *name, Error **errp)
742 {
743 Object **child = opaque;
744 bool ambiguous = false;
745 const char *type;
746 char *path;
747
748 type = object_property_get_type(obj, name, NULL);
749
750 visit_type_str(v, &path, name, errp);
751
752 if (*child) {
753 object_unref(*child);
754 }
755
756 if (strcmp(path, "") != 0) {
757 Object *target;
758
759 target = object_resolve_path(path, &ambiguous);
760 if (target) {
761 gchar *target_type;
762
763 target_type = g_strdup(&type[5]);
764 target_type[strlen(target_type) - 2] = 0;
765
766 if (object_dynamic_cast(target, target_type)) {
767 object_ref(target);
768 *child = target;
769 } else {
770 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
771 }
772
773 g_free(target_type);
774 } else {
775 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
776 }
777 } else {
778 *child = NULL;
779 }
780
781 g_free(path);
782 }
783
784 void object_property_add_link(Object *obj, const char *name,
785 const char *type, Object **child,
786 Error **errp)
787 {
788 gchar *full_type;
789
790 full_type = g_strdup_printf("link<%s>", type);
791
792 object_property_add(obj, name, full_type,
793 object_get_link_property,
794 object_set_link_property,
795 NULL, child, errp);
796
797 g_free(full_type);
798 }
799
800 gchar *object_get_canonical_path(Object *obj)
801 {
802 Object *root = object_get_root();
803 char *newpath = NULL, *path = NULL;
804
805 while (obj != root) {
806 ObjectProperty *prop = NULL;
807
808 g_assert(obj->parent != NULL);
809
810 QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
811 if (!strstart(prop->type, "child<", NULL)) {
812 continue;
813 }
814
815 if (prop->opaque == obj) {
816 if (path) {
817 newpath = g_strdup_printf("%s/%s", prop->name, path);
818 g_free(path);
819 path = newpath;
820 } else {
821 path = g_strdup(prop->name);
822 }
823 break;
824 }
825 }
826
827 g_assert(prop != NULL);
828
829 obj = obj->parent;
830 }
831
832 newpath = g_strdup_printf("/%s", path);
833 g_free(path);
834
835 return newpath;
836 }
837
838 static Object *object_resolve_abs_path(Object *parent,
839 gchar **parts,
840 int index)
841 {
842 ObjectProperty *prop;
843 Object *child;
844
845 if (parts[index] == NULL) {
846 return parent;
847 }
848
849 if (strcmp(parts[index], "") == 0) {
850 return object_resolve_abs_path(parent, parts, index + 1);
851 }
852
853 prop = object_property_find(parent, parts[index]);
854 if (prop == NULL) {
855 return NULL;
856 }
857
858 child = NULL;
859 if (strstart(prop->type, "link<", NULL)) {
860 Object **pchild = prop->opaque;
861 if (*pchild) {
862 child = *pchild;
863 }
864 } else if (strstart(prop->type, "child<", NULL)) {
865 child = prop->opaque;
866 }
867
868 if (!child) {
869 return NULL;
870 }
871
872 return object_resolve_abs_path(child, parts, index + 1);
873 }
874
875 static Object *object_resolve_partial_path(Object *parent,
876 gchar **parts,
877 bool *ambiguous)
878 {
879 Object *obj;
880 ObjectProperty *prop;
881
882 obj = object_resolve_abs_path(parent, parts, 0);
883
884 QTAILQ_FOREACH(prop, &parent->properties, node) {
885 Object *found;
886
887 if (!strstart(prop->type, "child<", NULL)) {
888 continue;
889 }
890
891 found = object_resolve_partial_path(prop->opaque, parts, ambiguous);
892 if (found) {
893 if (obj) {
894 if (ambiguous) {
895 *ambiguous = true;
896 }
897 return NULL;
898 }
899 obj = found;
900 }
901
902 if (ambiguous && *ambiguous) {
903 return NULL;
904 }
905 }
906
907 return obj;
908 }
909
910 Object *object_resolve_path(const char *path, bool *ambiguous)
911 {
912 bool partial_path = true;
913 Object *obj;
914 gchar **parts;
915
916 parts = g_strsplit(path, "/", 0);
917 if (parts == NULL || parts[0] == NULL) {
918 g_strfreev(parts);
919 return object_get_root();
920 }
921
922 if (strcmp(parts[0], "") == 0) {
923 partial_path = false;
924 }
925
926 if (partial_path) {
927 if (ambiguous) {
928 *ambiguous = false;
929 }
930 obj = object_resolve_partial_path(object_get_root(), parts, ambiguous);
931 } else {
932 obj = object_resolve_abs_path(object_get_root(), parts, 1);
933 }
934
935 g_strfreev(parts);
936
937 return obj;
938 }
939
940 typedef struct StringProperty
941 {
942 char *(*get)(Object *, Error **);
943 void (*set)(Object *, const char *, Error **);
944 } StringProperty;
945
946 static void object_property_get_str(Object *obj, Visitor *v, void *opaque,
947 const char *name, Error **errp)
948 {
949 StringProperty *prop = opaque;
950 char *value;
951
952 value = prop->get(obj, errp);
953 if (value) {
954 visit_type_str(v, &value, name, errp);
955 g_free(value);
956 }
957 }
958
959 static void object_property_set_str(Object *obj, Visitor *v, void *opaque,
960 const char *name, Error **errp)
961 {
962 StringProperty *prop = opaque;
963 char *value;
964 Error *local_err = NULL;
965
966 visit_type_str(v, &value, name, &local_err);
967 if (local_err) {
968 error_propagate(errp, local_err);
969 return;
970 }
971
972 prop->set(obj, value, errp);
973 g_free(value);
974 }
975
976 static void object_property_release_str(Object *obj, const char *name,
977 void *opaque)
978 {
979 StringProperty *prop = opaque;
980 g_free(prop);
981 }
982
983 void object_property_add_str(Object *obj, const char *name,
984 char *(*get)(Object *, Error **),
985 void (*set)(Object *, const char *, Error **),
986 Error **errp)
987 {
988 StringProperty *prop = g_malloc0(sizeof(*prop));
989
990 prop->get = get;
991 prop->set = set;
992
993 object_property_add(obj, name, "string",
994 get ? object_property_get_str : NULL,
995 set ? object_property_set_str : NULL,
996 object_property_release_str,
997 prop, errp);
998 }