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