/* addr-hash.c
*
* COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
*
* Hash tables for mapping addresses to objects.
*/
#include "ml-base.h"
#include "addr-hash.h"
typedef struct item { /* items in the hash table */
Addr_t addr; /* the address the object is keyed on */
void *obj; /* the object */
struct item *next; /* the next item in the bucket */
} item_t;
struct addr_tbl {
int ignoreBits;
int size;
int numItems;
Addr_t mask;
item_t **buckets;
};
#define HASH(tbl,addr) (((addr) >> (tbl)->ignoreBits) & (tbl)->mask)
/* MakeAddrTbl:
*
* Allocate an address hash table.
*/
addr_tbl_t *MakeAddrTbl (int ignoreBits, int size)
{
unsigned int nBuckets;
int i;
addr_tbl_t *tbl;
/* find smallest power of 2 (but at least 16) that is greater than size */
for (nBuckets = 16; nBuckets < size; nBuckets <<= 1)
continue;
tbl = NEW_OBJ(addr_tbl_t);
tbl->buckets = NEW_VEC(item_t *, nBuckets);
tbl->ignoreBits = ignoreBits;
tbl->size = nBuckets;
tbl->mask = nBuckets-1;
tbl->numItems = 0;
for (i = 0; i < nBuckets; i++)
tbl->buckets[i] = NIL(item_t *);
return tbl;
} /* end of MakeAddrTbl */
/* AddrTblInsert:
*
* Insert an object into a address hash table.
*/
void AddrTblInsert (addr_tbl_t *tbl, Addr_t addr, void *obj)
{
int h = HASH(tbl,addr);
item_t *p;
for (p = tbl->buckets[h]; (p != NIL(item_t *)) && (p->addr != addr); p = p->next)
continue;
if (p == NIL(item_t *)) {
p = NEW_OBJ(item_t);
p->addr = addr;
p->obj = obj;
p->next = tbl->buckets[h];
tbl->buckets[h] = p;
tbl->numItems++;
}
else if (p->obj != obj)
Die ("AddrTblInsert: %#x mapped to multiple objects", addr);
} /* end of AddrTblInsert */
/* AddrTblLookup:
*
* Return the object associated with the given address; return NIL, if not
* found.
*/
void *AddrTblLookup (addr_tbl_t *tbl, Addr_t addr)
{
int h = HASH(tbl,addr);
item_t *p;
for (p = tbl->buckets[h]; (p != NIL(item_t *)) && (p->addr != addr); p = p->next)
continue;
if (p == NIL(item_t *))
return NIL(void *);
else
return p->obj;
} /* end of AddrTblLookup */
/* AddrTblApply:
*
* Apply the given function to the elements of the table.
*/
void AddrTblApply (addr_tbl_t *tbl, void *clos, void (*f) (Addr_t, void *, void *))
{
int i;
item_t *p;
for (i = 0; i < tbl->size; i++) {
for (p = tbl->buckets[i]; p != NIL(item_t *); p = p->next) {
(*f) (p->addr, clos, p->obj);
}
}
} /* end of AddrTblApply */
/* FreeAddrTbl:
*
* Deallocate the space for an address table; if freeObjs is true, also deallocate
* the objects.
*/
void FreeAddrTbl (addr_tbl_t *tbl, bool_t freeObjs)
{
int i;
item_t *p, *q;
for (i = 0; i < tbl->size; i++) {
for (p = tbl->buckets[i]; p != NIL(item_t *); ) {
q = p->next;
if (freeObjs)
FREE (p->obj);
FREE (p);
p = q;
}
}
FREE (tbl->buckets);
FREE (tbl);
} /* end of FreeAddrTbl. */
syntax highlighted by Code2HTML, v. 0.9.1