4 * Copyright IBM, Corp. 2011
7 * Anthony Liguori <aliguori@us.ibm.com>
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.
13 #include "qemu/object.h"
14 #include "qemu-common.h"
16 #define MAX_INTERFACES 32
18 typedef struct InterfaceImpl InterfaceImpl
;
19 typedef struct TypeImpl TypeImpl
;
24 void (*interface_initfn
)(ObjectClass
*class, void *data
);
36 void (*class_init
)(ObjectClass
*klass
, void *data
);
37 void (*class_finalize
)(ObjectClass
*klass
, void *data
);
41 void (*instance_init
)(Object
*obj
);
42 void (*instance_finalize
)(Object
*obj
);
47 TypeImpl
*parent_type
;
52 InterfaceImpl interfaces
[MAX_INTERFACES
];
55 typedef struct Interface
61 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
63 static GHashTable
*type_table_get(void)
65 static GHashTable
*type_table
;
67 if (type_table
== NULL
) {
68 type_table
= g_hash_table_new(g_str_hash
, g_str_equal
);
74 static void type_table_add(TypeImpl
*ti
)
76 g_hash_table_insert(type_table_get(), (void *)ti
->name
, ti
);
79 static TypeImpl
*type_table_lookup(const char *name
)
81 return g_hash_table_lookup(type_table_get(), name
);
84 TypeImpl
*type_register(const TypeInfo
*info
)
86 TypeImpl
*ti
= g_malloc0(sizeof(*ti
));
88 g_assert(info
->name
!= NULL
);
90 if (type_table_lookup(info
->name
) != NULL
) {
91 fprintf(stderr
, "Registering `%s' which already exists\n", info
->name
);
95 ti
->name
= g_strdup(info
->name
);
96 ti
->parent
= g_strdup(info
->parent
);
98 ti
->class_size
= info
->class_size
;
99 ti
->instance_size
= info
->instance_size
;
101 ti
->class_init
= info
->class_init
;
102 ti
->class_finalize
= info
->class_finalize
;
103 ti
->class_data
= info
->class_data
;
105 ti
->instance_init
= info
->instance_init
;
106 ti
->instance_finalize
= info
->instance_finalize
;
108 ti
->abstract
= info
->abstract
;
110 if (info
->interfaces
) {
113 for (i
= 0; info
->interfaces
[i
].type
; i
++) {
114 ti
->interfaces
[i
].parent
= info
->interfaces
[i
].type
;
115 ti
->interfaces
[i
].interface_initfn
= info
->interfaces
[i
].interface_initfn
;
116 ti
->num_interfaces
++;
125 TypeImpl
*type_register_static(const TypeInfo
*info
)
127 return type_register(info
);
130 static TypeImpl
*type_get_by_name(const char *name
)
136 return type_table_lookup(name
);
139 static TypeImpl
*type_get_parent(TypeImpl
*type
)
141 if (!type
->parent_type
&& type
->parent
) {
142 type
->parent_type
= type_get_by_name(type
->parent
);
143 g_assert(type
->parent_type
!= NULL
);
146 return type
->parent_type
;
149 static bool type_has_parent(TypeImpl
*type
)
151 return (type
->parent
!= NULL
);
154 static size_t type_class_get_size(TypeImpl
*ti
)
156 if (ti
->class_size
) {
157 return ti
->class_size
;
160 if (type_has_parent(ti
)) {
161 return type_class_get_size(type_get_parent(ti
));
164 return sizeof(ObjectClass
);
167 static void type_class_interface_init(TypeImpl
*ti
, InterfaceImpl
*iface
)
170 .instance_size
= sizeof(Interface
),
171 .parent
= iface
->parent
,
172 .class_size
= sizeof(InterfaceClass
),
173 .class_init
= iface
->interface_initfn
,
176 char *name
= g_strdup_printf("<%s::%s>", ti
->name
, iface
->parent
);
179 iface
->type
= type_register(&info
);
183 static void type_class_init(TypeImpl
*ti
)
185 size_t class_size
= sizeof(ObjectClass
);
192 ti
->class_size
= type_class_get_size(ti
);
194 ti
->class = g_malloc0(ti
->class_size
);
195 ti
->class->type
= ti
;
197 if (type_has_parent(ti
)) {
198 TypeImpl
*parent
= type_get_parent(ti
);
200 type_class_init(parent
);
202 class_size
= parent
->class_size
;
203 g_assert(parent
->class_size
<= ti
->class_size
);
205 memcpy((void *)ti
->class + sizeof(ObjectClass
),
206 (void *)parent
->class + sizeof(ObjectClass
),
207 parent
->class_size
- sizeof(ObjectClass
));
210 memset((void *)ti
->class + class_size
, 0, ti
->class_size
- class_size
);
212 for (i
= 0; i
< ti
->num_interfaces
; i
++) {
213 type_class_interface_init(ti
, &ti
->interfaces
[i
]);
216 if (ti
->class_init
) {
217 ti
->class_init(ti
->class, ti
->class_data
);
221 static void object_interface_init(Object
*obj
, InterfaceImpl
*iface
)
223 TypeImpl
*ti
= iface
->type
;
224 Interface
*iface_obj
;
226 iface_obj
= INTERFACE(object_new(ti
->name
));
227 iface_obj
->obj
= obj
;
229 obj
->interfaces
= g_slist_prepend(obj
->interfaces
, iface_obj
);
232 static void object_init_with_type(Object
*obj
, TypeImpl
*ti
)
236 if (type_has_parent(ti
)) {
237 object_init_with_type(obj
, type_get_parent(ti
));
240 for (i
= 0; i
< ti
->num_interfaces
; i
++) {
241 object_interface_init(obj
, &ti
->interfaces
[i
]);
244 if (ti
->instance_init
) {
245 ti
->instance_init(obj
);
249 void object_initialize_with_type(void *data
, TypeImpl
*type
)
253 g_assert(type
!= NULL
);
254 g_assert(type
->instance_size
>= sizeof(ObjectClass
));
256 type_class_init(type
);
257 g_assert(type
->abstract
== false);
259 memset(obj
, 0, type
->instance_size
);
260 obj
->class = type
->class;
261 object_init_with_type(obj
, type
);
264 void object_initialize(void *data
, const char *typename
)
266 TypeImpl
*type
= type_get_by_name(typename
);
268 object_initialize_with_type(data
, type
);
271 static void object_deinit(Object
*obj
, TypeImpl
*type
)
273 if (type
->instance_finalize
) {
274 type
->instance_finalize(obj
);
277 while (obj
->interfaces
) {
278 Interface
*iface_obj
= obj
->interfaces
->data
;
279 obj
->interfaces
= g_slist_delete_link(obj
->interfaces
, obj
->interfaces
);
280 object_delete(OBJECT(iface_obj
));
283 if (type_has_parent(type
)) {
284 object_deinit(obj
, type_get_parent(type
));
288 void object_finalize(void *data
)
291 TypeImpl
*ti
= obj
->class->type
;
293 object_deinit(obj
, ti
);
296 Object
*object_new_with_type(Type type
)
300 g_assert(type
!= NULL
);
302 obj
= g_malloc(type
->instance_size
);
303 object_initialize_with_type(obj
, type
);
308 Object
*object_new(const char *typename
)
310 TypeImpl
*ti
= type_get_by_name(typename
);
312 return object_new_with_type(ti
);
315 void object_delete(Object
*obj
)
317 object_finalize(obj
);
321 static bool object_is_type(Object
*obj
, const char *typename
)
323 TypeImpl
*target_type
= type_get_by_name(typename
);
324 TypeImpl
*type
= obj
->class->type
;
327 /* Check if typename is a direct ancestor of type */
329 if (type
== target_type
) {
333 type
= type_get_parent(type
);
336 /* Check if obj has an interface of typename */
337 for (i
= obj
->interfaces
; i
; i
= i
->next
) {
338 Interface
*iface
= i
->data
;
340 if (object_is_type(OBJECT(iface
), typename
)) {
348 Object
*object_dynamic_cast(Object
*obj
, const char *typename
)
352 /* Check if typename is a direct ancestor */
353 if (object_is_type(obj
, typename
)) {
357 /* Check if obj has an interface of typename */
358 for (i
= obj
->interfaces
; i
; i
= i
->next
) {
359 Interface
*iface
= i
->data
;
361 if (object_is_type(OBJECT(iface
), typename
)) {
362 return OBJECT(iface
);
366 /* Check if obj is an interface and its containing object is a direct
367 * ancestor of typename */
368 if (object_is_type(obj
, TYPE_INTERFACE
)) {
369 Interface
*iface
= INTERFACE(obj
);
371 if (object_is_type(iface
->obj
, typename
)) {
380 static void register_interface(void)
382 static TypeInfo interface_info
= {
383 .name
= TYPE_INTERFACE
,
384 .instance_size
= sizeof(Interface
),
388 type_register_static(&interface_info
);
391 device_init(register_interface
);
393 Object
*object_dynamic_cast_assert(Object
*obj
, const char *typename
)
397 inst
= object_dynamic_cast(obj
, typename
);
400 fprintf(stderr
, "Object %p is not an instance of type %s\n",
408 ObjectClass
*object_class_dynamic_cast(ObjectClass
*class,
409 const char *typename
)
411 TypeImpl
*target_type
= type_get_by_name(typename
);
412 TypeImpl
*type
= class->type
;
415 if (type
== target_type
) {
419 type
= type_get_parent(type
);
425 ObjectClass
*object_class_dynamic_cast_assert(ObjectClass
*class,
426 const char *typename
)
428 ObjectClass
*ret
= object_class_dynamic_cast(class, typename
);
431 fprintf(stderr
, "Object %p is not an instance of type %s\n",
439 const char *object_get_typename(Object
*obj
)
441 return obj
->class->type
->name
;
444 ObjectClass
*object_get_class(Object
*obj
)
449 const char *object_class_get_name(ObjectClass
*klass
)
451 return klass
->type
->name
;
454 ObjectClass
*object_class_by_name(const char *typename
)
456 TypeImpl
*type
= type_get_by_name(typename
);
462 type_class_init(type
);
467 typedef struct OCFData
469 void (*fn
)(ObjectClass
*klass
, void *opaque
);
473 static void object_class_foreach_tramp(gpointer key
, gpointer value
,
476 OCFData
*data
= opaque
;
477 TypeImpl
*type
= value
;
479 type_class_init(type
);
481 data
->fn(value
, type
->class);
484 void object_class_foreach(void (*fn
)(ObjectClass
*klass
, void *opaque
),
487 OCFData data
= { fn
, opaque
};
489 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp
, &data
);