/* --------------------------------------------------------------------- */ /* BEGIN COPYRIGHT AND LICENSE NOTICE */ /* --------------------------------------------------------------------- */ /* ** Copyright (c) 2009 by Richard Harter. ** ** Permission is hereby granted, free of charge, to any person ** obtaining a copy of this software and associated documentation ** files (the "Software"), to deal in the Software without ** restriction, including without limitation the rights to use, ** copy, modify, merge, publish, distribute, sublicense, and/or ** sell copies of the Software, and to permit persons to whom the ** Software is furnished to do so, subject to the following ** conditions: ** ** The above copyright notice and this permission notice shall be ** included in copies of this software and in copies of substantial ** portions, whether or not the software has been modified. ** ** Derivative works shall include a notice that the software is a ** modified version of the copyrighted software. ** ** There is no guarantee that this software is useful for anything ** or that it is any way correct or of value. The author disclaims ** any responsibility for the consequences of using this software. ** */ /* --------------------------------------------------------------------- */ /* END COPYRIGHT AND LICENSE NOTICE */ /* --------------------------------------------------------------------- */ #include #include "trace.h" #include "getspace.h" #include "errmgr.h" #include "stgpool.h" #include "lineloc.h" #include "objtab.h" struct objslot_s { /* Object table slot */ union { /* Union */ void * object; /* Object pointer */ size_t link_index; /* Free list, index form */ } u; /* Union name */ size_t seqno; /* Slot sequence number */ }; struct objtab_s { objslot_s * slots; /* Array of object slots */ size_t slots_sz; /* Size of slots array */ size_t head; /* Head of the free list */ stgpool_s * pool; /* Storage pool to use, if any */ BOOLEAN closed; /* TRue is closed table, F is open */ }; static char *no_table = "Reference to a non-existent object table.\n"; static char *in_use = "Object table is damaged.\n"; static struct objtab_s init_objtab; BOOLEAN objtab_compare(object_rs obj1,object_rs obj2) { return ((obj1.index == obj2.index) && (obj1.seqno == obj2.seqno)); } BOOLEAN objtab_close(objtab_s * objtab, char * loc) { trace("objtab_close"); if (!objtab) errexit(loc,no_table); if (!objtab->pool) { if (objtab->slots) freespace(objtab->slots,LINELOC); freespace(objtab,LINELOC); } objtab->closed = TRUE; return TRUE; } BOOLEAN objtab_delete(objtab_s * tab,object_rs object_r, char * loc) { size_t index; trace("objtab_delete"); if (!tab) errexit(loc,no_table); index = object_r.index; if ((1 & tab->slots[index].seqno) || (tab->slots[index].seqno != object_r.seqno)) { return FALSE; } tab->slots[index].seqno++; tab->slots[index].u.link_index = tab->head; tab->head = tab->slots[index].u.link_index; return TRUE; } void * objtab_get(objtab_s *tab,object_rs ref,char * loc) { size_t index; void * object = 0; trace("objtab_get"); if (!tab) errexit(loc,no_table); index = ref.index; return ((index < tab->slots_sz) && (tab->slots[index].seqno == ref.seqno)) ? tab->slots[index].u.object : object; } object_rs objtab_insert(objtab_s * tab, void * item, stgpool_s * pool) { size_t old_sz; size_t index; size_t last; int i; object_rs ref; trace("objtab_insert"); if (!tab->head) { old_sz = tab->slots_sz; tab->slots = exparray(tab->slots,&tab->slots_sz, sizeof tab->slots[0],pool,LINELOC); for (i=old_sz;islots_sz-1;i++) { tab->slots[i].u.link_index = i+1; tab->slots[i].seqno = 1; } last = tab->slots_sz-1; tab->head = old_sz?old_sz:1; tab->slots[last].seqno = 1; tab->slots[last].u.link_index = 0; } index = tab->head; tab->slots[index].seqno++; if (1 & (tab->slots[index].seqno)) errexit(LINELOC,in_use); tab->head = tab->slots[index].u.link_index; tab->slots[index].u.object = item; ref.index = index; ref.seqno = tab->slots[index].seqno; return ref; } void * objtab_iter(objtab_s * tab,size_t * index, char * loc) { size_t i; trace("objtab_iter"); if (!tab) errexit(loc,no_table); if (*index >= tab->slots_sz) return 0; for (i= *index;islots_sz;i++) { if (1 & tab->slots[i].seqno) continue; *index = i+1; return tab->slots[i].u.object; } return 0; } objtab_s * objtab_open(stgpool_s * pool,char *loc) { objtab_s * objtab; trace("objtab_open"); if (pool) { objtab = stgpool_get(pool,sizeof(*pool),loc); *objtab = init_objtab; } else { objtab = getspace(sizeof(*pool),loc); *objtab = init_objtab; } objtab->pool = pool; return objtab; } BOOLEAN objtab_stale(objtab_s * tab,object_rs object_r, char * loc) { trace("objtab_stale"); return object_r.seqno != tab->slots[object_r.index].seqno; } BOOLEAN objtab_valid(objtab_s * tab,object_rs object_r,char * loc) { trace("objtab_valid"); if (!tab) errexit(loc,no_table); if (1 & object_r.seqno) return FALSE; if (object_r.index >= tab->slots_sz) return FALSE; return TRUE; }