]> Git Repo - qemu.git/blob - qom/object.c
target-ppc: Add read and write of PPR SPR
[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 "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 (!target_type) {
457         /* target class type unknown, so fail the cast */
458         return NULL;
459     }
460
461     if (type->class->interfaces &&
462             type_is_ancestor(target_type, type_interface)) {
463         int found = 0;
464         GSList *i;
465
466         for (i = class->interfaces; i; i = i->next) {
467             ObjectClass *target_class = i->data;
468
469             if (type_is_ancestor(target_class->type, target_type)) {
470                 ret = target_class;
471                 found++;
472             }
473          }
474
475         /* The match was ambiguous, don't allow a cast */
476         if (found > 1) {
477             ret = NULL;
478         }
479     } else if (type_is_ancestor(type, target_type)) {
480         ret = class;
481     }
482
483     return ret;
484 }
485
486 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
487                                               const char *typename)
488 {
489     ObjectClass *ret = object_class_dynamic_cast(class, typename);
490
491     if (!ret) {
492         fprintf(stderr, "Object %p is not an instance of type %s\n",
493                 class, typename);
494         abort();
495     }
496
497     return ret;
498 }
499
500 const char *object_get_typename(Object *obj)
501 {
502     return obj->class->type->name;
503 }
504
505 ObjectClass *object_get_class(Object *obj)
506 {
507     return obj->class;
508 }
509
510 bool object_class_is_abstract(ObjectClass *klass)
511 {
512     return klass->type->abstract;
513 }
514
515 const char *object_class_get_name(ObjectClass *klass)
516 {
517     return klass->type->name;
518 }
519
520 ObjectClass *object_class_by_name(const char *typename)
521 {
522     TypeImpl *type = type_get_by_name(typename);
523
524     if (!type) {
525         return NULL;
526     }
527
528     type_initialize(type);
529
530     return type->class;
531 }
532
533 ObjectClass *object_class_get_parent(ObjectClass *class)
534 {
535     TypeImpl *type = type_get_parent(class->type);
536
537     if (!type) {
538         return NULL;
539     }
540
541     type_initialize(type);
542
543     return type->class;
544 }
545
546 typedef struct OCFData
547 {
548     void (*fn)(ObjectClass *klass, void *opaque);
549     const char *implements_type;
550     bool include_abstract;
551     void *opaque;
552 } OCFData;
553
554 static void object_class_foreach_tramp(gpointer key, gpointer value,
555                                        gpointer opaque)
556 {
557     OCFData *data = opaque;
558     TypeImpl *type = value;
559     ObjectClass *k;
560
561     type_initialize(type);
562     k = type->class;
563
564     if (!data->include_abstract && type->abstract) {
565         return;
566     }
567
568     if (data->implements_type && 
569         !object_class_dynamic_cast(k, data->implements_type)) {
570         return;
571     }
572
573     data->fn(k, data->opaque);
574 }
575
576 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
577                           const char *implements_type, bool include_abstract,
578                           void *opaque)
579 {
580     OCFData data = { fn, implements_type, include_abstract, opaque };
581
582     g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
583 }
584
585 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
586                          void *opaque)
587 {
588     ObjectProperty *prop;
589     int ret = 0;
590
591     QTAILQ_FOREACH(prop, &obj->properties, node) {
592         if (object_property_is_child(prop)) {
593             ret = fn(prop->opaque, opaque);
594             if (ret != 0) {
595                 break;
596             }
597         }
598     }
599     return ret;
600 }
601
602 static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
603 {
604     GSList **list = opaque;
605
606     *list = g_slist_prepend(*list, klass);
607 }
608
609 GSList *object_class_get_list(const char *implements_type,
610                               bool include_abstract)
611 {
612     GSList *list = NULL;
613
614     object_class_foreach(object_class_get_list_tramp,
615                          implements_type, include_abstract, &list);
616     return list;
617 }
618
619 void object_ref(Object *obj)
620 {
621     obj->ref++;
622 }
623
624 void object_unref(Object *obj)
625 {
626     g_assert(obj->ref > 0);
627     obj->ref--;
628
629     /* parent always holds a reference to its children */
630     if (obj->ref == 0) {
631         object_finalize(obj);
632     }
633 }
634
635 void object_property_add(Object *obj, const char *name, const char *type,
636                          ObjectPropertyAccessor *get,
637                          ObjectPropertyAccessor *set,
638                          ObjectPropertyRelease *release,
639                          void *opaque, Error **errp)
640 {
641     ObjectProperty *prop;
642
643     QTAILQ_FOREACH(prop, &obj->properties, node) {
644         if (strcmp(prop->name, name) == 0) {
645             error_setg(errp, "attempt to add duplicate property '%s'"
646                        " to object (type '%s')", name,
647                        object_get_typename(obj));
648             return;
649         }
650     }
651
652     prop = g_malloc0(sizeof(*prop));
653
654     prop->name = g_strdup(name);
655     prop->type = g_strdup(type);
656
657     prop->get = get;
658     prop->set = set;
659     prop->release = release;
660     prop->opaque = opaque;
661
662     QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
663 }
664
665 ObjectProperty *object_property_find(Object *obj, const char *name,
666                                      Error **errp)
667 {
668     ObjectProperty *prop;
669
670     QTAILQ_FOREACH(prop, &obj->properties, node) {
671         if (strcmp(prop->name, name) == 0) {
672             return prop;
673         }
674     }
675
676     error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
677     return NULL;
678 }
679
680 void object_property_del(Object *obj, const char *name, Error **errp)
681 {
682     ObjectProperty *prop = object_property_find(obj, name, errp);
683     if (prop == NULL) {
684         return;
685     }
686
687     if (prop->release) {
688         prop->release(obj, name, prop->opaque);
689     }
690
691     QTAILQ_REMOVE(&obj->properties, prop, node);
692
693     g_free(prop->name);
694     g_free(prop->type);
695     g_free(prop);
696 }
697
698 void object_property_get(Object *obj, Visitor *v, const char *name,
699                          Error **errp)
700 {
701     ObjectProperty *prop = object_property_find(obj, name, errp);
702     if (prop == NULL) {
703         return;
704     }
705
706     if (!prop->get) {
707         error_set(errp, QERR_PERMISSION_DENIED);
708     } else {
709         prop->get(obj, v, prop->opaque, name, errp);
710     }
711 }
712
713 void object_property_set(Object *obj, Visitor *v, const char *name,
714                          Error **errp)
715 {
716     ObjectProperty *prop = object_property_find(obj, name, errp);
717     if (prop == NULL) {
718         return;
719     }
720
721     if (!prop->set) {
722         error_set(errp, QERR_PERMISSION_DENIED);
723     } else {
724         prop->set(obj, v, prop->opaque, name, errp);
725     }
726 }
727
728 void object_property_set_str(Object *obj, const char *value,
729                              const char *name, Error **errp)
730 {
731     QString *qstr = qstring_from_str(value);
732     object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
733
734     QDECREF(qstr);
735 }
736
737 char *object_property_get_str(Object *obj, const char *name,
738                               Error **errp)
739 {
740     QObject *ret = object_property_get_qobject(obj, name, errp);
741     QString *qstring;
742     char *retval;
743
744     if (!ret) {
745         return NULL;
746     }
747     qstring = qobject_to_qstring(ret);
748     if (!qstring) {
749         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
750         retval = NULL;
751     } else {
752         retval = g_strdup(qstring_get_str(qstring));
753     }
754
755     QDECREF(qstring);
756     return retval;
757 }
758
759 void object_property_set_link(Object *obj, Object *value,
760                               const char *name, Error **errp)
761 {
762     object_property_set_str(obj, object_get_canonical_path(value),
763                             name, errp);
764 }
765
766 Object *object_property_get_link(Object *obj, const char *name,
767                                  Error **errp)
768 {
769     char *str = object_property_get_str(obj, name, errp);
770     Object *target = NULL;
771
772     if (str && *str) {
773         target = object_resolve_path(str, NULL);
774         if (!target) {
775             error_set(errp, QERR_DEVICE_NOT_FOUND, str);
776         }
777     }
778
779     g_free(str);
780     return target;
781 }
782
783 void object_property_set_bool(Object *obj, bool value,
784                               const char *name, Error **errp)
785 {
786     QBool *qbool = qbool_from_int(value);
787     object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
788
789     QDECREF(qbool);
790 }
791
792 bool object_property_get_bool(Object *obj, const char *name,
793                               Error **errp)
794 {
795     QObject *ret = object_property_get_qobject(obj, name, errp);
796     QBool *qbool;
797     bool retval;
798
799     if (!ret) {
800         return false;
801     }
802     qbool = qobject_to_qbool(ret);
803     if (!qbool) {
804         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
805         retval = false;
806     } else {
807         retval = qbool_get_int(qbool);
808     }
809
810     QDECREF(qbool);
811     return retval;
812 }
813
814 void object_property_set_int(Object *obj, int64_t value,
815                              const char *name, Error **errp)
816 {
817     QInt *qint = qint_from_int(value);
818     object_property_set_qobject(obj, QOBJECT(qint), name, errp);
819
820     QDECREF(qint);
821 }
822
823 int64_t object_property_get_int(Object *obj, const char *name,
824                                 Error **errp)
825 {
826     QObject *ret = object_property_get_qobject(obj, name, errp);
827     QInt *qint;
828     int64_t retval;
829
830     if (!ret) {
831         return -1;
832     }
833     qint = qobject_to_qint(ret);
834     if (!qint) {
835         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
836         retval = -1;
837     } else {
838         retval = qint_get_int(qint);
839     }
840
841     QDECREF(qint);
842     return retval;
843 }
844
845 void object_property_parse(Object *obj, const char *string,
846                            const char *name, Error **errp)
847 {
848     StringInputVisitor *mi;
849     mi = string_input_visitor_new(string);
850     object_property_set(obj, string_input_get_visitor(mi), name, errp);
851
852     string_input_visitor_cleanup(mi);
853 }
854
855 char *object_property_print(Object *obj, const char *name,
856                             Error **errp)
857 {
858     StringOutputVisitor *mo;
859     char *string;
860
861     mo = string_output_visitor_new();
862     object_property_get(obj, string_output_get_visitor(mo), name, errp);
863     string = string_output_get_string(mo);
864     string_output_visitor_cleanup(mo);
865     return string;
866 }
867
868 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
869 {
870     ObjectProperty *prop = object_property_find(obj, name, errp);
871     if (prop == NULL) {
872         return NULL;
873     }
874
875     return prop->type;
876 }
877
878 Object *object_get_root(void)
879 {
880     static Object *root;
881
882     if (!root) {
883         root = object_new("container");
884     }
885
886     return root;
887 }
888
889 static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
890                                       const char *name, Error **errp)
891 {
892     Object *child = opaque;
893     gchar *path;
894
895     path = object_get_canonical_path(child);
896     visit_type_str(v, &path, name, errp);
897     g_free(path);
898 }
899
900 static void object_finalize_child_property(Object *obj, const char *name,
901                                            void *opaque)
902 {
903     Object *child = opaque;
904
905     object_unref(child);
906 }
907
908 void object_property_add_child(Object *obj, const char *name,
909                                Object *child, Error **errp)
910 {
911     gchar *type;
912
913     type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
914
915     object_property_add(obj, name, type, object_get_child_property,
916                         NULL, object_finalize_child_property, child, errp);
917
918     object_ref(child);
919     g_assert(child->parent == NULL);
920     child->parent = obj;
921
922     g_free(type);
923 }
924
925 static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
926                                      const char *name, Error **errp)
927 {
928     Object **child = opaque;
929     gchar *path;
930
931     if (*child) {
932         path = object_get_canonical_path(*child);
933         visit_type_str(v, &path, name, errp);
934         g_free(path);
935     } else {
936         path = (gchar *)"";
937         visit_type_str(v, &path, name, errp);
938     }
939 }
940
941 static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
942                                      const char *name, Error **errp)
943 {
944     Object **child = opaque;
945     Object *old_target;
946     bool ambiguous = false;
947     const char *type;
948     char *path;
949     gchar *target_type;
950
951     type = object_property_get_type(obj, name, NULL);
952
953     visit_type_str(v, &path, name, errp);
954
955     old_target = *child;
956     *child = NULL;
957
958     if (strcmp(path, "") != 0) {
959         Object *target;
960
961         /* Go from link<FOO> to FOO.  */
962         target_type = g_strndup(&type[5], strlen(type) - 6);
963         target = object_resolve_path_type(path, target_type, &ambiguous);
964
965         if (ambiguous) {
966             error_set(errp, QERR_AMBIGUOUS_PATH, path);
967         } else if (target) {
968             object_ref(target);
969             *child = target;
970         } else {
971             target = object_resolve_path(path, &ambiguous);
972             if (target || ambiguous) {
973                 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
974             } else {
975                 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
976             }
977         }
978         g_free(target_type);
979     }
980
981     g_free(path);
982
983     if (old_target != NULL) {
984         object_unref(old_target);
985     }
986 }
987
988 void object_property_add_link(Object *obj, const char *name,
989                               const char *type, Object **child,
990                               Error **errp)
991 {
992     gchar *full_type;
993
994     full_type = g_strdup_printf("link<%s>", type);
995
996     object_property_add(obj, name, full_type,
997                         object_get_link_property,
998                         object_set_link_property,
999                         NULL, child, errp);
1000
1001     g_free(full_type);
1002 }
1003
1004 gchar *object_get_canonical_path(Object *obj)
1005 {
1006     Object *root = object_get_root();
1007     char *newpath = NULL, *path = NULL;
1008
1009     while (obj != root) {
1010         ObjectProperty *prop = NULL;
1011
1012         g_assert(obj->parent != NULL);
1013
1014         QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
1015             if (!object_property_is_child(prop)) {
1016                 continue;
1017             }
1018
1019             if (prop->opaque == obj) {
1020                 if (path) {
1021                     newpath = g_strdup_printf("%s/%s", prop->name, path);
1022                     g_free(path);
1023                     path = newpath;
1024                 } else {
1025                     path = g_strdup(prop->name);
1026                 }
1027                 break;
1028             }
1029         }
1030
1031         g_assert(prop != NULL);
1032
1033         obj = obj->parent;
1034     }
1035
1036     newpath = g_strdup_printf("/%s", path);
1037     g_free(path);
1038
1039     return newpath;
1040 }
1041
1042 Object *object_resolve_path_component(Object *parent, const gchar *part)
1043 {
1044     ObjectProperty *prop = object_property_find(parent, part, NULL);
1045     if (prop == NULL) {
1046         return NULL;
1047     }
1048
1049     if (object_property_is_link(prop)) {
1050         return *(Object **)prop->opaque;
1051     } else if (object_property_is_child(prop)) {
1052         return prop->opaque;
1053     } else {
1054         return NULL;
1055     }
1056 }
1057
1058 static Object *object_resolve_abs_path(Object *parent,
1059                                           gchar **parts,
1060                                           const char *typename,
1061                                           int index)
1062 {
1063     Object *child;
1064
1065     if (parts[index] == NULL) {
1066         return object_dynamic_cast(parent, typename);
1067     }
1068
1069     if (strcmp(parts[index], "") == 0) {
1070         return object_resolve_abs_path(parent, parts, typename, index + 1);
1071     }
1072
1073     child = object_resolve_path_component(parent, parts[index]);
1074     if (!child) {
1075         return NULL;
1076     }
1077
1078     return object_resolve_abs_path(child, parts, typename, index + 1);
1079 }
1080
1081 static Object *object_resolve_partial_path(Object *parent,
1082                                               gchar **parts,
1083                                               const char *typename,
1084                                               bool *ambiguous)
1085 {
1086     Object *obj;
1087     ObjectProperty *prop;
1088
1089     obj = object_resolve_abs_path(parent, parts, typename, 0);
1090
1091     QTAILQ_FOREACH(prop, &parent->properties, node) {
1092         Object *found;
1093
1094         if (!object_property_is_child(prop)) {
1095             continue;
1096         }
1097
1098         found = object_resolve_partial_path(prop->opaque, parts,
1099                                             typename, ambiguous);
1100         if (found) {
1101             if (obj) {
1102                 if (ambiguous) {
1103                     *ambiguous = true;
1104                 }
1105                 return NULL;
1106             }
1107             obj = found;
1108         }
1109
1110         if (ambiguous && *ambiguous) {
1111             return NULL;
1112         }
1113     }
1114
1115     return obj;
1116 }
1117
1118 Object *object_resolve_path_type(const char *path, const char *typename,
1119                                  bool *ambiguous)
1120 {
1121     Object *obj;
1122     gchar **parts;
1123
1124     parts = g_strsplit(path, "/", 0);
1125     assert(parts);
1126
1127     if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
1128         if (ambiguous) {
1129             *ambiguous = false;
1130         }
1131         obj = object_resolve_partial_path(object_get_root(), parts,
1132                                           typename, ambiguous);
1133     } else {
1134         obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1135     }
1136
1137     g_strfreev(parts);
1138
1139     return obj;
1140 }
1141
1142 Object *object_resolve_path(const char *path, bool *ambiguous)
1143 {
1144     return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1145 }
1146
1147 typedef struct StringProperty
1148 {
1149     char *(*get)(Object *, Error **);
1150     void (*set)(Object *, const char *, Error **);
1151 } StringProperty;
1152
1153 static void property_get_str(Object *obj, Visitor *v, void *opaque,
1154                              const char *name, Error **errp)
1155 {
1156     StringProperty *prop = opaque;
1157     char *value;
1158
1159     value = prop->get(obj, errp);
1160     if (value) {
1161         visit_type_str(v, &value, name, errp);
1162         g_free(value);
1163     }
1164 }
1165
1166 static void property_set_str(Object *obj, Visitor *v, void *opaque,
1167                              const char *name, Error **errp)
1168 {
1169     StringProperty *prop = opaque;
1170     char *value;
1171     Error *local_err = NULL;
1172
1173     visit_type_str(v, &value, name, &local_err);
1174     if (local_err) {
1175         error_propagate(errp, local_err);
1176         return;
1177     }
1178
1179     prop->set(obj, value, errp);
1180     g_free(value);
1181 }
1182
1183 static void property_release_str(Object *obj, const char *name,
1184                                  void *opaque)
1185 {
1186     StringProperty *prop = opaque;
1187     g_free(prop);
1188 }
1189
1190 void object_property_add_str(Object *obj, const char *name,
1191                            char *(*get)(Object *, Error **),
1192                            void (*set)(Object *, const char *, Error **),
1193                            Error **errp)
1194 {
1195     StringProperty *prop = g_malloc0(sizeof(*prop));
1196
1197     prop->get = get;
1198     prop->set = set;
1199
1200     object_property_add(obj, name, "string",
1201                         get ? property_get_str : NULL,
1202                         set ? property_set_str : NULL,
1203                         property_release_str,
1204                         prop, errp);
1205 }
1206
1207 typedef struct BoolProperty
1208 {
1209     bool (*get)(Object *, Error **);
1210     void (*set)(Object *, bool, Error **);
1211 } BoolProperty;
1212
1213 static void property_get_bool(Object *obj, Visitor *v, void *opaque,
1214                               const char *name, Error **errp)
1215 {
1216     BoolProperty *prop = opaque;
1217     bool value;
1218
1219     value = prop->get(obj, errp);
1220     visit_type_bool(v, &value, name, errp);
1221 }
1222
1223 static void property_set_bool(Object *obj, Visitor *v, void *opaque,
1224                               const char *name, Error **errp)
1225 {
1226     BoolProperty *prop = opaque;
1227     bool value;
1228     Error *local_err = NULL;
1229
1230     visit_type_bool(v, &value, name, &local_err);
1231     if (local_err) {
1232         error_propagate(errp, local_err);
1233         return;
1234     }
1235
1236     prop->set(obj, value, errp);
1237 }
1238
1239 static void property_release_bool(Object *obj, const char *name,
1240                                   void *opaque)
1241 {
1242     BoolProperty *prop = opaque;
1243     g_free(prop);
1244 }
1245
1246 void object_property_add_bool(Object *obj, const char *name,
1247                               bool (*get)(Object *, Error **),
1248                               void (*set)(Object *, bool, Error **),
1249                               Error **errp)
1250 {
1251     BoolProperty *prop = g_malloc0(sizeof(*prop));
1252
1253     prop->get = get;
1254     prop->set = set;
1255
1256     object_property_add(obj, name, "bool",
1257                         get ? property_get_bool : NULL,
1258                         set ? property_set_bool : NULL,
1259                         property_release_bool,
1260                         prop, errp);
1261 }
1262
1263 static char *qdev_get_type(Object *obj, Error **errp)
1264 {
1265     return g_strdup(object_get_typename(obj));
1266 }
1267
1268 static void object_instance_init(Object *obj)
1269 {
1270     object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
1271 }
1272
1273 static void register_types(void)
1274 {
1275     static TypeInfo interface_info = {
1276         .name = TYPE_INTERFACE,
1277         .class_size = sizeof(InterfaceClass),
1278         .abstract = true,
1279     };
1280
1281     static TypeInfo object_info = {
1282         .name = TYPE_OBJECT,
1283         .instance_size = sizeof(Object),
1284         .instance_init = object_instance_init,
1285         .abstract = true,
1286     };
1287
1288     type_interface = type_register_internal(&interface_info);
1289     type_register_internal(&object_info);
1290 }
1291
1292 type_init(register_types)
This page took 0.089614 seconds and 4 git commands to generate.