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