Reorganize build system
[qemu/aliguori.git] / qom / type.c
blobde9751d1221f2a4b8c596e3d49a3eb6b3bab7ffa
1 #include "qemu/type.h"
2 #include <glib.h>
4 #define MAX_INTERFACES 32
6 typedef struct InterfaceImpl
8 const char *parent;
9 void (*interface_initfn)(TypeClass *class);
10 Type type;
11 } InterfaceImpl;
13 typedef struct TypeImpl
15 const char *name;
16 Type type;
18 size_t class_size;
20 size_t instance_size;
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);
31 const char *parent;
33 TypeClass *class;
35 int num_interfaces;
36 InterfaceImpl interfaces[MAX_INTERFACES];
37 } TypeImpl;
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++;
45 TypeImpl *ti;
47 ti = &type_table[type];
49 assert(info->name != NULL);
51 ti->name = info->name;
52 ti->parent = info->parent;
53 ti->type = type;
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) {
68 int i;
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;
73 ti->num_interfaces++;
77 return type;
80 static Type type_register_anonymous(const TypeInfo *info)
82 Type type = num_types++;
83 TypeImpl *ti;
84 char buffer[32];
85 static int count;
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);
92 ti->type = type;
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) {
107 int i;
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++;
116 return type;
119 static TypeImpl *type_get_instance(Type type)
121 assert(type != 0);
122 assert(type < num_types);
124 return &type_table[type];
127 Type type_get_by_name(const char *name)
129 int i;
131 if (name == NULL) {
132 return 0;
135 for (i = 1; i < num_types; i++) {
136 if (strcmp(name, type_table[i].name) == 0) {
137 return i;
141 return 0;
144 static void type_class_base_init(TypeImpl *base_ti, const char *typename)
146 TypeImpl *ti;
148 if (!typename) {
149 return;
152 ti = type_get_instance(type_get_by_name(typename));
154 type_class_base_init(base_ti, ti->parent);
156 if (ti->base_init) {
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;
167 if (ti->parent) {
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)
176 TypeInfo info = {
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);
188 int i;
190 if (ti->class) {
191 return;
194 ti->class_size = type_class_get_size(ti);
196 ti->class = qemu_malloc(ti->class_size);
197 ti->class->type = ti->type;
199 if (ti->parent) {
200 TypeImpl *ti_parent;
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;
231 static int count;
232 char buffer[32];
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));
244 int i;
246 if (ti->parent) {
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));
268 type_class_init(ti);
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));
298 if (ti->parent) {
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);
316 return ti->name;
319 TypeInstance *type_new(const char *typename, const char *id)
321 TypeImpl *ti = type_get_instance(type_get_by_name(typename));
322 TypeInstance *obj;
324 obj = qemu_malloc(ti->instance_size);
325 type_initialize(obj, typename, id);
327 return obj;
330 void type_delete(TypeInstance *obj)
332 type_finalize(obj);
333 qemu_free(obj);
336 TypeInstance *type_find_by_id(const char *id)
338 gpointer data;
340 if (global_object_table == NULL) {
341 return NULL;
344 data = g_hash_table_lookup(global_object_table, id);
346 if (!data) {
347 return NULL;
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 */
359 while (type) {
360 TypeImpl *ti = type_get_instance(type);
362 if (ti->type == target_type) {
363 return true;
366 type = type_get_by_name(ti->parent);
369 return false;
372 TypeInstance *type_dynamic_cast(TypeInstance *obj, const char *typename)
374 GSList *i;
376 /* Check if typename is a direct ancestor */
377 if (type_is_type(obj, typename)) {
378 return obj;
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)) {
395 return iface->obj;
399 return NULL;
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)
415 TypeInstance *inst;
417 inst = type_dynamic_cast(obj, typename);
419 if (!inst) {
420 fprintf(stderr, "Object %p is not an instance of type %s\n", obj, typename);
421 abort();
424 return inst;
427 TypeClass *type_check_class(TypeClass *class, const char *typename)
429 Type target_type = type_get_by_name(typename);
430 Type type = class->type;
432 while (type) {
433 TypeImpl *ti = type_get_instance(type);
435 if (ti->type == target_type) {
436 return class;
439 type = type_get_by_name(ti->parent);
442 fprintf(stderr, "Object %p is not an instance of type %d\n", class, (int)type);
443 abort();
445 return NULL;
448 const char *type_get_id(TypeInstance *obj)
450 return obj->id;
453 const char *type_get_type(TypeInstance *obj)
455 return type_get_name(obj->class->type);
458 TypeClass *type_get_class(TypeInstance *obj)
460 return obj->class;
463 typedef struct TypeForeachData
465 void (*enumfn)(TypeInstance *obj, void *opaque);
466 void *opaque;
467 } TypeForeachData;
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 = {
478 .enumfn = enumfn,
479 .opaque = opaque,
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;