4 #define MAX_INTERFACES 32
6 typedef struct InterfaceImpl
9 void (*interface_initfn
)(TypeClass
*class);
13 typedef struct TypeImpl
22 void (*base_init
)(TypeClass
*klass
);
23 void (*base_finalize
)(TypeClass
*klass
);
25 void (*class_init
)(TypeClass
*klass
);
26 void (*class_finalize
)(TypeClass
*klass
);
28 void (*instance_init
)(TypeInstance
*obj
);
29 void (*instance_finalize
)(TypeInstance
*obj
);
36 InterfaceImpl interfaces
[MAX_INTERFACES
];
39 static int num_types
= 1;
40 static TypeImpl type_table
[128];
42 Type
type_register_static(const TypeInfo
*info
)
44 Type type
= num_types
++;
47 ti
= &type_table
[type
];
49 assert(info
->name
!= NULL
);
51 ti
->name
= info
->name
;
52 ti
->parent
= info
->parent
;
55 ti
->class_size
= info
->class_size
;
56 ti
->instance_size
= info
->instance_size
;
58 ti
->base_init
= info
->base_init
;
59 ti
->base_finalize
= info
->base_finalize
;
61 ti
->class_init
= info
->class_init
;
62 ti
->class_finalize
= info
->class_finalize
;
64 ti
->instance_init
= info
->instance_init
;
65 ti
->instance_finalize
= info
->instance_finalize
;
67 if (info
->interfaces
) {
70 for (i
= 0; info
->interfaces
[i
].type
; i
++) {
71 ti
->interfaces
[i
].parent
= info
->interfaces
[i
].type
;
72 ti
->interfaces
[i
].interface_initfn
= info
->interfaces
[i
].interface_initfn
;
80 static Type
type_register_anonymous(const TypeInfo
*info
)
82 Type type
= num_types
++;
87 ti
= &type_table
[type
];
89 snprintf(buffer
, sizeof(buffer
), "<anonymous-%d>", count
++);
90 ti
->name
= qemu_strdup(buffer
);
91 ti
->parent
= qemu_strdup(info
->parent
);
94 ti
->class_size
= info
->class_size
;
95 ti
->instance_size
= info
->instance_size
;
97 ti
->base_init
= info
->base_init
;
98 ti
->base_finalize
= info
->base_finalize
;
100 ti
->class_init
= info
->class_init
;
101 ti
->class_finalize
= info
->class_finalize
;
103 ti
->instance_init
= info
->instance_init
;
104 ti
->instance_finalize
= info
->instance_finalize
;
106 if (info
->interfaces
) {
109 for (i
= 0; info
->interfaces
[i
].type
; i
++) {
110 ti
->interfaces
[i
].parent
= info
->interfaces
[i
].type
;
111 ti
->interfaces
[i
].interface_initfn
= info
->interfaces
[i
].interface_initfn
;
112 ti
->num_interfaces
++;
119 static TypeImpl
*type_get_instance(Type type
)
122 assert(type
< num_types
);
124 return &type_table
[type
];
127 Type
type_get_by_name(const char *name
)
135 for (i
= 1; i
< num_types
; i
++) {
136 if (strcmp(name
, type_table
[i
].name
) == 0) {
144 static void type_class_base_init(TypeImpl
*base_ti
, const char *typename
)
152 ti
= type_get_instance(type_get_by_name(typename
));
154 type_class_base_init(base_ti
, ti
->parent
);
157 ti
->base_init(base_ti
->class);
161 static size_t type_class_get_size(TypeImpl
*ti
)
163 if (ti
->class_size
) {
164 return ti
->class_size
;
168 return type_class_get_size(type_get_instance(type_get_by_name(ti
->parent
)));
171 return sizeof(TypeClass
);
174 static void type_class_interface_init(TypeImpl
*ti
, InterfaceImpl
*iface
)
177 .instance_size
= sizeof(Interface
),
178 .parent
= iface
->parent
,
179 .class_init
= iface
->interface_initfn
,
182 iface
->type
= type_register_anonymous(&info
);
185 static void type_class_init(TypeImpl
*ti
)
187 size_t class_size
= sizeof(TypeClass
);
194 ti
->class_size
= type_class_get_size(ti
);
196 ti
->class = qemu_malloc(ti
->class_size
);
197 ti
->class->type
= ti
->type
;
202 ti_parent
= type_get_instance(type_get_by_name(ti
->parent
));
204 type_class_init(ti_parent
);
206 class_size
= ti_parent
->class_size
;
207 assert(ti_parent
->class_size
<= ti
->class_size
);
209 memcpy((void *)ti
->class + sizeof(TypeClass
),
210 (void *)ti_parent
->class + sizeof(TypeClass
),
211 ti_parent
->class_size
- sizeof(TypeClass
));
214 memset((void *)ti
->class + class_size
, 0, ti
->class_size
- class_size
);
216 type_class_base_init(ti
, ti
->parent
);
218 for (i
= 0; i
< ti
->num_interfaces
; i
++) {
219 type_class_interface_init(ti
, &ti
->interfaces
[i
]);
222 if (ti
->class_init
) {
223 ti
->class_init(ti
->class);
227 static void type_instance_interface_init(TypeInstance
*obj
, InterfaceImpl
*iface
)
229 TypeImpl
*ti
= type_get_instance(iface
->type
);
230 Interface
*iface_obj
;
234 snprintf(buffer
, sizeof(buffer
), "__anonymous_%d", count
++);
235 iface_obj
= INTERFACE(type_new(ti
->name
, buffer
));
236 iface_obj
->obj
= obj
;
238 obj
->interfaces
= g_slist_prepend(obj
->interfaces
, iface_obj
);
241 static void type_instance_init(TypeInstance
*obj
, const char *typename
)
243 TypeImpl
*ti
= type_get_instance(type_get_by_name(typename
));
247 type_instance_init(obj
, ti
->parent
);
250 for (i
= 0; i
< ti
->num_interfaces
; i
++) {
251 type_instance_interface_init(obj
, &ti
->interfaces
[i
]);
254 if (ti
->instance_init
) {
255 ti
->instance_init(obj
);
259 static GHashTable
*global_object_table
;
261 void type_initialize(void *data
, const char *typename
, const char *id
)
263 TypeImpl
*ti
= type_get_instance(type_get_by_name(typename
));
264 TypeInstance
*obj
= data
;
266 assert(ti
->instance_size
>= sizeof(TypeClass
));
270 memset(obj
, 0, ti
->instance_size
);
272 obj
->class = ti
->class;
273 snprintf(obj
->id
, sizeof(obj
->id
), "%s", id
);
275 if (global_object_table
== NULL
) {
276 global_object_table
= g_hash_table_new(g_str_hash
, g_str_equal
);
279 g_hash_table_insert(global_object_table
, obj
->id
, obj
);
281 type_instance_init(obj
, typename
);
284 static void type_instance_finalize(TypeInstance
*obj
, const char *typename
)
286 TypeImpl
*ti
= type_get_instance(type_get_by_name(typename
));
288 if (ti
->instance_finalize
) {
289 ti
->instance_finalize(obj
);
292 while (obj
->interfaces
) {
293 Interface
*iface_obj
= obj
->interfaces
->data
;
294 obj
->interfaces
= g_slist_delete_link(obj
->interfaces
, obj
->interfaces
);
295 type_delete(TYPE_INSTANCE(iface_obj
));
299 type_instance_init(obj
, ti
->parent
);
303 void type_finalize(void *data
)
305 TypeInstance
*obj
= data
;
306 TypeImpl
*ti
= type_get_instance(obj
->class->type
);
308 g_hash_table_remove(global_object_table
, obj
->id
);
310 type_instance_finalize(obj
, ti
->name
);
313 const char *type_get_name(Type type
)
315 TypeImpl
*ti
= type_get_instance(type
);
319 TypeInstance
*type_new(const char *typename
, const char *id
)
321 TypeImpl
*ti
= type_get_instance(type_get_by_name(typename
));
324 obj
= qemu_malloc(ti
->instance_size
);
325 type_initialize(obj
, typename
, id
);
330 void type_delete(TypeInstance
*obj
)
336 TypeInstance
*type_find_by_id(const char *id
)
340 if (global_object_table
== NULL
) {
344 data
= g_hash_table_lookup(global_object_table
, id
);
350 return TYPE_INSTANCE(data
);
353 bool type_is_type(TypeInstance
*obj
, const char *typename
)
355 Type target_type
= type_get_by_name(typename
);
356 Type type
= obj
->class->type
;
358 /* Check if typename is a direct ancestor of type */
360 TypeImpl
*ti
= type_get_instance(type
);
362 if (ti
->type
== target_type
) {
366 type
= type_get_by_name(ti
->parent
);
372 TypeInstance
*type_dynamic_cast(TypeInstance
*obj
, const char *typename
)
376 /* Check if typename is a direct ancestor */
377 if (type_is_type(obj
, typename
)) {
381 /* Check if obj has an interface of typename */
382 for (i
= obj
->interfaces
; i
; i
= i
->next
) {
383 Interface
*iface
= i
->data
;
385 if (type_is_type(TYPE_INSTANCE(iface
), typename
)) {
386 return TYPE_INSTANCE(iface
);
390 /* Check if obj is an interface and it's containing object is a direct ancestor of typename */
391 if (type_is_type(obj
, TYPE_INTERFACE
)) {
392 Interface
*iface
= INTERFACE(obj
);
394 if (type_is_type(iface
->obj
, typename
)) {
402 void type_system_init(void)
404 static TypeInfo interface_info
= {
405 .name
= TYPE_INTERFACE
,
406 .instance_size
= sizeof(Interface
),
407 .class_size
= sizeof(TypeInterface
),
410 type_register_static(&interface_info
);
413 TypeInstance
*type_dynamic_cast_assert(TypeInstance
*obj
, const char *typename
)
417 inst
= type_dynamic_cast(obj
, typename
);
420 fprintf(stderr
, "Object %p is not an instance of type %s\n", obj
, typename
);
427 TypeClass
*type_check_class(TypeClass
*class, const char *typename
)
429 Type target_type
= type_get_by_name(typename
);
430 Type type
= class->type
;
433 TypeImpl
*ti
= type_get_instance(type
);
435 if (ti
->type
== target_type
) {
439 type
= type_get_by_name(ti
->parent
);
442 fprintf(stderr
, "Object %p is not an instance of type %d\n", class, (int)type
);
448 const char *type_get_id(TypeInstance
*obj
)
453 const char *type_get_type(TypeInstance
*obj
)
455 return type_get_name(obj
->class->type
);
458 TypeClass
*type_get_class(TypeInstance
*obj
)
463 typedef struct TypeForeachData
465 void (*enumfn
)(TypeInstance
*obj
, void *opaque
);
469 static void type_foreach_tramp(gpointer key
, gpointer value
, gpointer opaque
)
471 TypeForeachData
*data
= opaque
;
472 data
->enumfn(TYPE_INSTANCE(value
), data
->opaque
);
475 void type_foreach(void (*enumfn
)(TypeInstance
*obj
, void *opaque
), void *opaque
)
477 TypeForeachData data
= {
482 g_hash_table_foreach(global_object_table
, type_foreach_tramp
, &data
);
485 TypeClass
*type_get_super(TypeInstance
*obj
)
487 return type_get_instance(type_get_by_name(type_get_instance(obj
->class->type
)->parent
))->class;