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