// 17 may 2015 #include "../ui.h" #include "uipriv.h" struct typeinfo { const char *name; uintmax_t parent; size_t size; }; static struct ptrArray *types = NULL; uintmax_t uiRegisterType(const char *name, uintmax_t parent, size_t size) { struct typeinfo *ti; if (types == NULL) { types = newPtrArray(); // reserve ID 0 ptrArrayAppend(types, NULL); } // TODO prevent our size from being smaller than our parent's ti = uiNew(struct typeinfo); ti->name = name; ti->parent = parent; ti->size = size; ptrArrayAppend(types, ti); return types->len - 1; } void *uiIsA(void *p, uintmax_t id, int fail) { uiTyped *t; struct typeinfo *ti, *ti2; uintmax_t compareTo; if (id == 0 || id >= types->len) complain("invalid type ID given to uiIsA()"); t = (uiTyped *) p; compareTo = t->Type; if (compareTo == 0) complain("object %p has no type in uiIsA()", t); for (;;) { if (compareTo >= types->len) complain("invalid type ID in uiIsA()", t); if (compareTo == id) return t; ti = ptrArrayIndex(types, struct typeinfo *, compareTo); if (ti->parent == 0) break; compareTo = ti->parent; } if (fail) { ti = ptrArrayIndex(types, struct typeinfo *, id); ti2 = ptrArrayIndex(types, struct typeinfo *, t->Type); complain("object %p not a %s in uiIsA() (is a %s)", t, ti->name, ti2->name); } return NULL; } void uninitTypes(void) { struct typeinfo *ti; if (types == NULL) // never initialized; do nothing return; // the first entry is NULL; get rid of it directly ptrArrayDelete(types, 0); while (types->len != 0) { ti = ptrArrayIndex(types, struct typeinfo *, 0); ptrArrayDelete(types, 0); uiFree(ti); } ptrArrayDestroy(types); } uiTyped *newTyped(uintmax_t type) { struct typeinfo *ti; uiTyped *instance; if (type == 0 || type >= types->len) complain("invalid type ID given to newTyped()"); ti = ptrArrayIndex(types, struct typeinfo *, type); instance = (uiTyped *) uiAlloc(ti->size, ti->name); instance->Type = type; return instance; }