X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/0bd984429304da7c1c5509103e3dc04149028a95..aab9ab9fdd05119855383b33b67b27dcec5f3902:/sym.c diff --git a/sym.c b/sym.c index fb3806b..394b761 100644 --- a/sym.c +++ b/sym.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: sym.c,v 1.4 1999/05/06 19:51:35 mdw Exp $ + * $Id: sym.c,v 1.7 1999/06/01 09:49:08 mdw Exp $ * * Symbol table management * @@ -30,6 +30,16 @@ /*----- Revision history --------------------------------------------------* * * $Log: sym.c,v $ + * Revision 1.7 1999/06/01 09:49:08 mdw + * Allow things to be looked up by just their caller-supplied hashes. This + * actually needs to be thought through better. + * + * Revision 1.6 1999/05/26 21:08:31 mdw + * Rename symbols in line with newer conventions. + * + * Revision 1.5 1999/05/13 22:48:37 mdw + * Twiddle the extension threshold. Change `-ise' to `-ize' throughout. + * * Revision 1.4 1999/05/06 19:51:35 mdw * Reformatted the LGPL notice a little bit. * @@ -55,6 +65,7 @@ /* --- Local headers --- */ #include "alloc.h" +#include "bits.h" #include "crc32.h" #include "exc.h" #include "sub.h" @@ -78,26 +89,23 @@ * and the limit %$l$% satisfy the relation %$n < bl$%; if a new item is * added to the table and this relation is found to be false, the table is * doubled in size. - * - * The current function gives %$l = {3n \over 4}$%, which appears to be - * reasonable on the face of things. */ -#define SYM_LIMIT(n) (((n) * 3) >> 2) /* Load factor for growing table */ +#define SYM_LIMIT(n) ((n) * 4) /* Load factor for growing table */ /*----- Main code ---------------------------------------------------------*/ -/* --- @sym_createTable@ --- * +/* --- @sym_create@ --- * * - * Arguments: @sym_table *t@ = symbol table to initialise + * Arguments: @sym_table *t@ = symbol table to initialize * * Returns: --- * - * Use: Initialises the given symbol table. Raises @EXC_NOMEM@ if + * Use: Initializes the given symbol table. Raises @EXC_NOMEM@ if * there isn't enough memory. */ -void sym_createTable(sym_table *t) +void sym_create(sym_table *t) { size_t i; @@ -114,7 +122,7 @@ void sym_createTable(sym_table *t) TRACK_POP; } -/* --- @sym_destroyTable@ --- * +/* --- @sym_destroy@ --- * * * Arguments: @sym_table *t@ = pointer to symbol table in question * @@ -124,7 +132,7 @@ void sym_createTable(sym_table *t) * occupy. */ -void sym_destroyTable(sym_table *t) +void sym_destroy(sym_table *t) { size_t i; sym_base *p, *q; @@ -163,7 +171,9 @@ void sym_destroyTable(sym_table *t) * may be given, in which case the name may contain arbitrary * binary data, or it may be given as a negative number, in * which case the length of the name is calculated as - * @strlen(n) + 1@. + * @strlen(n) + 1@. The name pointer @n@ may also be zero; in + * this case, @l@ is taken to be a raw hash, and any element + * with a matching hash is taken to be the one wanted. * * The return value is the address of a pointer to a @sym_base@ * block (which may have other things on the end, as above). If @@ -180,22 +190,26 @@ void sym_destroyTable(sym_table *t) void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f) { - unsigned long hash; /* Hash value for user's name */ - size_t len = l < 0 ? strlen(n) + 1 : l; /* Find length of user's name */ - sym_base *bin; /* Bin containing our item */ - sym_base *p, *q; /* Pointer wandering through list */ + uint32 hash; + size_t len = 0; + sym_base *bin; + sym_base *p, *q; /* --- Find the correct bin --- */ - CRC32(hash, 0, n, len); /* Find hash value for this name */ + if (n) { + len = l < 0 ? strlen(n) + 1 : l; + CRC32(hash, 0, n, len); + } else + hash = (uint32)l; bin = p = (sym_base *)(t->a + (hash & t->mask)); /* --- Search the bin list --- */ while (p->next) { - if (hash == p->next->hash && /* Check full hash values first */ - len == p->next->len && /* Then compare string lengths */ - !memcmp(n, SYM_NAME(p->next), len)) /* And finally compare names */ + if (hash == p->next->hash && + (n == 0 || (len == p->next->len && + !memcmp(n, SYM_NAME(p->next), len)))) { /* --- Found a match --- * * @@ -203,61 +217,63 @@ void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f) * front of its bin list. */ - q = p->next; /* Find the actual symbol block */ - p->next = q->next; /* Extract block from bin list */ - q->next = bin->next; /* Set up symbol's next pointer */ - bin->next = q; /* And reinsert the block */ + q = p->next; + p->next = q->next; + q->next = bin->next; + bin->next = q; /* --- Return the block --- */ - if (f) *f = 1; /* Didn't fail to find the item */ - return (q); /* And return the block */ + if (f) *f = 1; + return (q); } - p = p->next; /* Move onto the next item */ + p = p->next; } /* --- Couldn't find the item there --- */ - if (f) *f = 0; /* Failed to find the block */ - if (!sz) return (0); /* Return zero if not creating */ + if (f) *f = 0; + if (!sz) return (0); - /* --- Create a new symbol block and initialise it --- */ + /* --- Create a new symbol block and initialize it --- */ { TRACK_CTX("new symbol creation"); TRACK_PUSH; - p = xmalloc(sz); /* Create a new symbol block */ - p->next = bin->next; /* Set up the next pointer */ - p->hash = hash; /* Set up the hash value too */ - p->len = len; /* And set up the string length */ - if (len <= SYM_BUFSZ) - memcpy(p->name.b, n, len); /* And copy the string over */ - else { - TRY { - p->name.p = sub_alloc(len); /* Allocate a block for the name */ - memcpy(p->name.p, n, len); /* And copy the string over */ - } CATCH { - free(p); - TRACK_POP; - RETHROW; - } END_TRY; + p = xmalloc(sz); + p->next = bin->next; + p->hash = hash; + p->len = len; + if (n) { + if (len <= SYM_BUFSZ) + memcpy(p->name.b, n, len); + else { + TRY { + p->name.p = sub_alloc(len); + memcpy(p->name.p, n, len); + } CATCH { + free(p); + TRACK_POP; + RETHROW; + } END_TRY; + } } TRACK_POP; } - bin->next = p; /* Put the pointer into the bin */ + bin->next = p; /* --- Consider growing the array --- */ if (t->c) t->c--; if (!t->c) { - unsigned long m = t->mask + 1; /* Next set bit in has word */ - sym_base *p, *q, *r; /* More useful pointers */ - size_t i, lim; /* Loop counter and limit */ + uint32 m = t->mask + 1; + sym_base *p, *q, *r; + size_t i, lim; TRACK_CTX("symbol table extension"); TRACK_PUSH; @@ -275,8 +291,8 @@ void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f) RETHROW; } END_TRY; - t->c = SYM_LIMIT(t->mask + 1); /* Set load value */ - t->mask = (t->mask + 1) * 2 - 1; /* Set the new mask value */ + t->c = SYM_LIMIT(t->mask + 1); + t->mask = (t->mask + 1) * 2 - 1; /* --- Now wander through the table rehashing things --- * * @@ -288,22 +304,22 @@ void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f) lim = (t->mask + 1) >> 1; for (i = 0; i < lim; i++) { - /* --- Some initialisation --- */ + /* --- Some initialization --- */ - r = t->a[i]; /* Find the list we're dissecting */ - p = (sym_base *)(t->a + i); /* Find bit-clear list */ - q = (sym_base *)(t->a + i + lim); /* And the bit-set lsit */ + r = t->a[i]; + p = (sym_base *)(t->a + i); + q = (sym_base *)(t->a + i + lim); /* --- Now go through the @r@ list --- */ while (r) { - if (r->hash & m) /* Is the next bit set? */ - q = q->next = r; /* Yes, so fit up previous link */ + if (r->hash & m) + q = q->next = r; else - p = p->next = r; /* No, so fit up previous link */ - r = r->next; /* Move onto the next item */ + p = p->next = r; + r = r->next; } - p->next = q->next = 0; /* Null terminate the new lists */ + p->next = q->next = 0; } TRACK_POP; @@ -360,7 +376,7 @@ void sym_remove(sym_table *t, void *b) t->c++; } -/* --- @sym_createIter@ --- * +/* --- @sym_mkiter@ --- * * * Arguments: @sym_iter *i@ = pointer to an iterator object * @sym_table *t@ = pointer to a symbol table object @@ -371,7 +387,7 @@ void sym_remove(sym_table *t, void *b) * iterate through a symbol table. */ -void sym_createIter(sym_iter *i, sym_table *t) +void sym_mkiter(sym_iter *i, sym_table *t) { i->t = t; i->i = 0; @@ -442,7 +458,7 @@ int main(void) sym_table tbl; int entries; - /* --- Initialise for reading the file --- */ + /* --- Initialize for reading the file --- */ sz = BUFSIZ; buff = xmalloc(sz + 1); @@ -496,7 +512,7 @@ int main(void) flag[i] = 0; entries = 0; - sym_createTable(&tbl); + sym_create(&tbl); for (;;) { i = (unsigned)rand() % sz; @@ -569,7 +585,7 @@ int main(void) ntbl = xmalloc(sz * sizeof(sym_word *)); memcpy(ntbl, flag, sz * sizeof(sym_word *)); - sym_createIter(&it, &tbl); + sym_mkiter(&it, &tbl); while ((w = sym_next(&it)) != 0) { if (ntbl[w->i] == 0)