Index: trunk/src/extobj.c =================================================================== --- trunk/src/extobj.c (revision 25603) +++ trunk/src/extobj.c (revision 25604) @@ -28,22 +28,58 @@ #include #include +#include #include "extobj.h" -vtp0_t extobj_i2o; /* extobj_idx -> (pcb_ext_obj_t *) */ -htsi_t extobj_n2i; /* extobj name -> index */ +static htsi_t pcb_extobj_n2i; /* extobj name -> index */ +vtp0_t pcb_extobj_i2o; /* extobj_idx -> (pcb_ext_obj_t *) */ +int pcb_extobj_invalid; /* this changes upon each new extobj reg, forcing the caches to be invalidated eventually */ +void pcb_extobj_unreg(pcb_extobj_t *o) +{ + if (!o->registered) + return; + htsi_pop(&pcb_extobj_n2i, o->name); + vtp0_set(&pcb_extobj_i2o, o->idx, NULL); + o->registered = 0; + o->idx = 0; +} +void pcb_extobj_reg(pcb_extobj_t *o) +{ + o->idx = pcb_extobj_i2o.used; + vtp0_append(&pcb_extobj_i2o, o); + o->registered = 0; + htsi_set(&pcb_extobj_n2i, (char *)o->name, o->idx); + pcb_extobj_invalid = -o->idx; +} + +int pcb_extobj_lookup_idx(const char *name) +{ + return htsi_get(&pcb_extobj_n2i, (char *)name); +} + void pcb_extobj_init(void) { + vtp0_init(&pcb_extobj_i2o); + htsi_init(&pcb_extobj_n2i, strhash, strkeyeq); + vtp0_append(&pcb_extobj_i2o, NULL); /* idx=0 is reserved for no extended obj */ } void pcb_extobj_uninit(void) { + size_t n; + for(n = 0; n < pcb_extobj_i2o.used; n++) { + pcb_extobj_t *o = pcb_extobj_i2o.array[n]; + if (o != NULL) + pcb_extobj_unreg(o); + } + htsi_uninit(&pcb_extobj_n2i); + vtp0_uninit(&pcb_extobj_i2o); } Index: trunk/src/extobj.h =================================================================== --- trunk/src/extobj.h (revision 25603) +++ trunk/src/extobj.h (revision 25604) @@ -27,14 +27,55 @@ #ifndef PCB_EXT_OBJ_H #define PCB_EXT_OBJ_H +#include + #include "obj_common.h" #include "draw.h" -struct pcb_ext_obj_s { + +typedef struct pcb_extobj_s pcb_extobj_t; + +struct pcb_extobj_s { + /* static data - filled in by the extobj code */ + const char *name; void (*draw)(pcb_draw_info_t *info, pcb_any_obj_t *obj); + + /* dynamic data - filled in by core */ + int idx; + unsigned registered:1; }; void pcb_extobj_init(void); void pcb_extobj_uninit(void); +void pcb_extobj_unreg(pcb_extobj_t *o); +void pcb_extobj_reg(pcb_extobj_t *o); + +int pcb_extobj_lookup_idx(const char *name); + +extern int pcb_extobj_invalid; /* this changes upon each new extobj reg, forcing the caches to be invalidated eventually */ +extern vtp0_t pcb_extobj_i2o; /* extobj_idx -> (pcb_ext_obj_t *) */ + +PCB_INLINE pcb_extobj_t *pcb_extobj_get(pcb_any_obj_t *obj) +{ + pcb_extobj_t **eo; + + if ((obj->extobj == NULL) || (obj->extobj_idx == pcb_extobj_invalid)) + return NULL; /* known negative */ + + if (obj->extobj_idx <= 0) { /* invalid idx cache - look up by name */ + obj->extobj_idx = pcb_extobj_lookup_idx(obj->extobj); + if (obj->extobj_idx == 0) { /* no such name */ + obj->extobj_idx = pcb_extobj_invalid; /* make the next lookup cheaper */ + return NULL; + } + } + + eo = (pcb_extobj_t **)vtp0_get(&pcb_extobj_i2o, obj->extobj_idx, 0); + if ((eo == NULL) || (*eo == NULL)) /* extobj backend got deregistered meanwhile */ + obj->extobj_idx = pcb_extobj_invalid; /* make the next lookup cheaper */ + return *eo; +} + + #endif Index: trunk/src/obj_common.h =================================================================== --- trunk/src/obj_common.h (revision 25603) +++ trunk/src/obj_common.h (revision 25604) @@ -186,7 +186,7 @@ PCB_ANY_OBJ_FIELDS; \ const char *term; \ const char *extobj; \ - unsigned int extobj_idx; \ + int extobj_idx; \ void *ratconn; \ unsigned char thermal; \ unsigned char intconn, intnoconn; \