xref: /qemu/qom/object.c (revision b46d9b10)
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 
17 #define MAX_INTERFACES 32
18 
19 typedef struct InterfaceImpl InterfaceImpl;
20 typedef struct TypeImpl TypeImpl;
21 
22 struct InterfaceImpl
23 {
24     const char *parent;
25     void (*interface_initfn)(ObjectClass *class, void *data);
26     TypeImpl *type;
27 };
28 
29 struct TypeImpl
30 {
31     const char *name;
32 
33     size_t class_size;
34 
35     size_t instance_size;
36 
37     void (*class_init)(ObjectClass *klass, void *data);
38     void (*class_finalize)(ObjectClass *klass, void *data);
39 
40     void *class_data;
41 
42     void (*instance_init)(Object *obj);
43     void (*instance_finalize)(Object *obj);
44 
45     bool abstract;
46 
47     const char *parent;
48     TypeImpl *parent_type;
49 
50     ObjectClass *class;
51 
52     int num_interfaces;
53     InterfaceImpl interfaces[MAX_INTERFACES];
54 };
55 
56 typedef struct Interface
57 {
58     Object parent;
59     Object *obj;
60 } Interface;
61 
62 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
63 
64 static Type 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, TypeImpl *target_type)
388 {
389     return !target_type || type_is_ancestor(obj->class->type, target_type);
390 }
391 
392 Object *object_dynamic_cast(Object *obj, const char *typename)
393 {
394     TypeImpl *target_type = type_get_by_name(typename);
395     GSList *i;
396 
397     /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
398      * we want to go back from interfaces to the parent.
399     */
400     if (target_type && object_is_type(obj, target_type)) {
401         return obj;
402     }
403 
404     /* Check if obj is an interface and its containing object is a direct
405      * ancestor of typename.  In principle we could do this test at the very
406      * beginning of object_dynamic_cast, avoiding a second call to
407      * object_is_type.  However, casting between interfaces is relatively
408      * rare, and object_is_type(obj, type_interface) would fail almost always.
409      *
410      * Perhaps we could add a magic value to the object header for increased
411      * (run-time) type safety and to speed up tests like this one.  If we ever
412      * do that we can revisit the order here.
413      */
414     if (object_is_type(obj, type_interface)) {
415         assert(!obj->interfaces);
416         obj = INTERFACE(obj)->obj;
417         if (object_is_type(obj, target_type)) {
418             return obj;
419         }
420     }
421 
422     if (!target_type) {
423         return obj;
424     }
425 
426     /* Check if obj has an interface of typename */
427     for (i = obj->interfaces; i; i = i->next) {
428         Interface *iface = i->data;
429 
430         if (object_is_type(OBJECT(iface), target_type)) {
431             return OBJECT(iface);
432         }
433     }
434 
435     return NULL;
436 }
437 
438 
439 static void register_interface(void)
440 {
441     static TypeInfo interface_info = {
442         .name = TYPE_INTERFACE,
443         .instance_size = sizeof(Interface),
444         .abstract = true,
445     };
446 
447     type_interface = type_register_static(&interface_info);
448 }
449 
450 device_init(register_interface);
451 
452 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
453 {
454     Object *inst;
455 
456     inst = object_dynamic_cast(obj, typename);
457 
458     if (!inst) {
459         fprintf(stderr, "Object %p is not an instance of type %s\n",
460                 obj, typename);
461         abort();
462     }
463 
464     return inst;
465 }
466 
467 ObjectClass *object_class_dynamic_cast(ObjectClass *class,
468                                        const char *typename)
469 {
470     TypeImpl *target_type = type_get_by_name(typename);
471     TypeImpl *type = class->type;
472 
473     while (type) {
474         if (type == target_type) {
475             return class;
476         }
477 
478         type = type_get_parent(type);
479     }
480 
481     return NULL;
482 }
483 
484 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
485                                               const char *typename)
486 {
487     ObjectClass *ret = object_class_dynamic_cast(class, typename);
488 
489     if (!ret) {
490         fprintf(stderr, "Object %p is not an instance of type %s\n",
491                 class, typename);
492         abort();
493     }
494 
495     return ret;
496 }
497 
498 const char *object_get_typename(Object *obj)
499 {
500     return obj->class->type->name;
501 }
502 
503 ObjectClass *object_get_class(Object *obj)
504 {
505     return obj->class;
506 }
507 
508 const char *object_class_get_name(ObjectClass *klass)
509 {
510     return klass->type->name;
511 }
512 
513 ObjectClass *object_class_by_name(const char *typename)
514 {
515     TypeImpl *type = type_get_by_name(typename);
516 
517     if (!type) {
518         return NULL;
519     }
520 
521     type_class_init(type);
522 
523     return type->class;
524 }
525 
526 typedef struct OCFData
527 {
528     void (*fn)(ObjectClass *klass, void *opaque);
529     const char *implements_type;
530     bool include_abstract;
531     void *opaque;
532 } OCFData;
533 
534 static void object_class_foreach_tramp(gpointer key, gpointer value,
535                                        gpointer opaque)
536 {
537     OCFData *data = opaque;
538     TypeImpl *type = value;
539     ObjectClass *k;
540 
541     type_class_init(type);
542     k = type->class;
543 
544     if (!data->include_abstract && type->abstract) {
545         return;
546     }
547 
548     if (data->implements_type &&
549         !object_class_dynamic_cast(k, data->implements_type)) {
550         return;
551     }
552 
553     data->fn(k, data->opaque);
554 }
555 
556 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
557                           const char *implements_type, bool include_abstract,
558                           void *opaque)
559 {
560     OCFData data = { fn, implements_type, include_abstract, opaque };
561 
562     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
563 }
564 
565 void object_ref(Object *obj)
566 {
567     obj->ref++;
568 }
569 
570 void object_unref(Object *obj)
571 {
572     g_assert(obj->ref > 0);
573     obj->ref--;
574 
575     /* parent always holds a reference to its children */
576     if (obj->ref == 0) {
577         object_finalize(obj);
578     }
579 }
580 
581 void object_property_add(Object *obj, const char *name, const char *type,
582                          ObjectPropertyAccessor *get,
583                          ObjectPropertyAccessor *set,
584                          ObjectPropertyRelease *release,
585                          void *opaque, Error **errp)
586 {
587     ObjectProperty *prop = g_malloc0(sizeof(*prop));
588 
589     prop->name = g_strdup(name);
590     prop->type = g_strdup(type);
591 
592     prop->get = get;
593     prop->set = set;
594     prop->release = release;
595     prop->opaque = opaque;
596 
597     QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
598 }
599 
600 static ObjectProperty *object_property_find(Object *obj, const char *name)
601 {
602     ObjectProperty *prop;
603 
604     QTAILQ_FOREACH(prop, &obj->properties, node) {
605         if (strcmp(prop->name, name) == 0) {
606             return prop;
607         }
608     }
609 
610     return NULL;
611 }
612 
613 void object_property_del(Object *obj, const char *name, Error **errp)
614 {
615     ObjectProperty *prop = object_property_find(obj, name);
616 
617     QTAILQ_REMOVE(&obj->properties, prop, node);
618 
619     prop->release(obj, prop->name, prop->opaque);
620 
621     g_free(prop->name);
622     g_free(prop->type);
623     g_free(prop);
624 }
625 
626 void object_property_get(Object *obj, Visitor *v, const char *name,
627                          Error **errp)
628 {
629     ObjectProperty *prop = object_property_find(obj, name);
630 
631     if (prop == NULL) {
632         error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
633         return;
634     }
635 
636     if (!prop->get) {
637         error_set(errp, QERR_PERMISSION_DENIED);
638     } else {
639         prop->get(obj, v, prop->opaque, name, errp);
640     }
641 }
642 
643 void object_property_set(Object *obj, Visitor *v, const char *name,
644                          Error **errp)
645 {
646     ObjectProperty *prop = object_property_find(obj, name);
647 
648     if (prop == NULL) {
649         error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
650         return;
651     }
652 
653     if (!prop->set) {
654         error_set(errp, QERR_PERMISSION_DENIED);
655     } else {
656         prop->set(obj, v, prop->opaque, name, errp);
657     }
658 }
659 
660 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
661 {
662     ObjectProperty *prop = object_property_find(obj, name);
663 
664     if (prop == NULL) {
665         error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
666         return NULL;
667     }
668 
669     return prop->type;
670 }
671 
672 Object *object_get_root(void)
673 {
674     static Object *root;
675 
676     if (!root) {
677         root = object_new("container");
678     }
679 
680     return root;
681 }
682 
683 static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
684                                       const char *name, Error **errp)
685 {
686     Object *child = opaque;
687     gchar *path;
688 
689     path = object_get_canonical_path(child);
690     visit_type_str(v, &path, name, errp);
691     g_free(path);
692 }
693 
694 static void object_finalize_child_property(Object *obj, const char *name,
695                                            void *opaque)
696 {
697     Object *child = opaque;
698 
699     object_unref(child);
700 }
701 
702 void object_property_add_child(Object *obj, const char *name,
703                                Object *child, Error **errp)
704 {
705     gchar *type;
706 
707     type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
708 
709     object_property_add(obj, name, type, object_get_child_property,
710                         NULL, object_finalize_child_property, child, errp);
711 
712     object_ref(child);
713     g_assert(child->parent == NULL);
714     child->parent = obj;
715 
716     g_free(type);
717 }
718 
719 static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
720                                      const char *name, Error **errp)
721 {
722     Object **child = opaque;
723     gchar *path;
724 
725     if (*child) {
726         path = object_get_canonical_path(*child);
727         visit_type_str(v, &path, name, errp);
728         g_free(path);
729     } else {
730         path = (gchar *)"";
731         visit_type_str(v, &path, name, errp);
732     }
733 }
734 
735 static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
736                                      const char *name, Error **errp)
737 {
738     Object **child = opaque;
739     bool ambiguous = false;
740     const char *type;
741     char *path;
742 
743     type = object_property_get_type(obj, name, NULL);
744 
745     visit_type_str(v, &path, name, errp);
746 
747     if (*child) {
748         object_unref(*child);
749     }
750 
751     if (strcmp(path, "") != 0) {
752         Object *target;
753 
754         target = object_resolve_path(path, &ambiguous);
755         if (target) {
756             gchar *target_type;
757 
758             target_type = g_strdup(&type[5]);
759             target_type[strlen(target_type) - 2] = 0;
760 
761             if (object_dynamic_cast(target, target_type)) {
762                 object_ref(target);
763                 *child = target;
764             } else {
765                 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
766             }
767 
768             g_free(target_type);
769         } else {
770             error_set(errp, QERR_DEVICE_NOT_FOUND, path);
771         }
772     } else {
773         *child = NULL;
774     }
775 
776     g_free(path);
777 }
778 
779 void object_property_add_link(Object *obj, const char *name,
780                               const char *type, Object **child,
781                               Error **errp)
782 {
783     gchar *full_type;
784 
785     full_type = g_strdup_printf("link<%s>", type);
786 
787     object_property_add(obj, name, full_type,
788                         object_get_link_property,
789                         object_set_link_property,
790                         NULL, child, errp);
791 
792     g_free(full_type);
793 }
794 
795 gchar *object_get_canonical_path(Object *obj)
796 {
797     Object *root = object_get_root();
798     char *newpath = NULL, *path = NULL;
799 
800     while (obj != root) {
801         ObjectProperty *prop = NULL;
802 
803         g_assert(obj->parent != NULL);
804 
805         QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
806             if (!strstart(prop->type, "child<", NULL)) {
807                 continue;
808             }
809 
810             if (prop->opaque == obj) {
811                 if (path) {
812                     newpath = g_strdup_printf("%s/%s", prop->name, path);
813                     g_free(path);
814                     path = newpath;
815                 } else {
816                     path = g_strdup(prop->name);
817                 }
818                 break;
819             }
820         }
821 
822         g_assert(prop != NULL);
823 
824         obj = obj->parent;
825     }
826 
827     newpath = g_strdup_printf("/%s", path);
828     g_free(path);
829 
830     return newpath;
831 }
832 
833 static Object *object_resolve_abs_path(Object *parent,
834                                           gchar **parts,
835                                           int index)
836 {
837     ObjectProperty *prop;
838     Object *child;
839 
840     if (parts[index] == NULL) {
841         return parent;
842     }
843 
844     if (strcmp(parts[index], "") == 0) {
845         return object_resolve_abs_path(parent, parts, index + 1);
846     }
847 
848     prop = object_property_find(parent, parts[index]);
849     if (prop == NULL) {
850         return NULL;
851     }
852 
853     child = NULL;
854     if (strstart(prop->type, "link<", NULL)) {
855         Object **pchild = prop->opaque;
856         if (*pchild) {
857             child = *pchild;
858         }
859     } else if (strstart(prop->type, "child<", NULL)) {
860         child = prop->opaque;
861     }
862 
863     if (!child) {
864         return NULL;
865     }
866 
867     return object_resolve_abs_path(child, parts, index + 1);
868 }
869 
870 static Object *object_resolve_partial_path(Object *parent,
871                                               gchar **parts,
872                                               bool *ambiguous)
873 {
874     Object *obj;
875     ObjectProperty *prop;
876 
877     obj = object_resolve_abs_path(parent, parts, 0);
878 
879     QTAILQ_FOREACH(prop, &parent->properties, node) {
880         Object *found;
881 
882         if (!strstart(prop->type, "child<", NULL)) {
883             continue;
884         }
885 
886         found = object_resolve_partial_path(prop->opaque, parts, ambiguous);
887         if (found) {
888             if (obj) {
889                 if (ambiguous) {
890                     *ambiguous = true;
891                 }
892                 return NULL;
893             }
894             obj = found;
895         }
896 
897         if (ambiguous && *ambiguous) {
898             return NULL;
899         }
900     }
901 
902     return obj;
903 }
904 
905 Object *object_resolve_path(const char *path, bool *ambiguous)
906 {
907     bool partial_path = true;
908     Object *obj;
909     gchar **parts;
910 
911     parts = g_strsplit(path, "/", 0);
912     if (parts == NULL || parts[0] == NULL) {
913         g_strfreev(parts);
914         return object_get_root();
915     }
916 
917     if (strcmp(parts[0], "") == 0) {
918         partial_path = false;
919     }
920 
921     if (partial_path) {
922         if (ambiguous) {
923             *ambiguous = false;
924         }
925         obj = object_resolve_partial_path(object_get_root(), parts, ambiguous);
926     } else {
927         obj = object_resolve_abs_path(object_get_root(), parts, 1);
928     }
929 
930     g_strfreev(parts);
931 
932     return obj;
933 }
934 
935 typedef struct StringProperty
936 {
937     char *(*get)(Object *, Error **);
938     void (*set)(Object *, const char *, Error **);
939 } StringProperty;
940 
941 static void object_property_get_str(Object *obj, Visitor *v, void *opaque,
942                                     const char *name, Error **errp)
943 {
944     StringProperty *prop = opaque;
945     char *value;
946 
947     value = prop->get(obj, errp);
948     if (value) {
949         visit_type_str(v, &value, name, errp);
950         g_free(value);
951     }
952 }
953 
954 static void object_property_set_str(Object *obj, Visitor *v, void *opaque,
955                                   const char *name, Error **errp)
956 {
957     StringProperty *prop = opaque;
958     char *value;
959     Error *local_err = NULL;
960 
961     visit_type_str(v, &value, name, &local_err);
962     if (local_err) {
963         error_propagate(errp, local_err);
964         return;
965     }
966 
967     prop->set(obj, value, errp);
968     g_free(value);
969 }
970 
971 static void object_property_release_str(Object *obj, const char *name,
972                                       void *opaque)
973 {
974     StringProperty *prop = opaque;
975     g_free(prop);
976 }
977 
978 void object_property_add_str(Object *obj, const char *name,
979                            char *(*get)(Object *, Error **),
980                            void (*set)(Object *, const char *, Error **),
981                            Error **errp)
982 {
983     StringProperty *prop = g_malloc0(sizeof(*prop));
984 
985     prop->get = get;
986     prop->set = set;
987 
988     object_property_add(obj, name, "string",
989                         get ? object_property_get_str : NULL,
990                         set ? object_property_set_str : NULL,
991                         object_property_release_str,
992                         prop, errp);
993 }
994