// htab.cpp - table hashing routines // // $Id: htab.cpp,v 1.1 2000/04/11 07:14:45 sdennis Exp $ // // MUX 2.0 // Portions are derived from MUX 1.6. Portions are original work. // // Copyright (C) 1998 through 2000 Solid Vertical Domains, Ltd. All // rights not explicitly given are reserved. Permission is given to // use this code for building and hosting text-based game servers. // Permission is given to use this code for other non-commercial // purposes. To use this code for commercial purposes other than // building/hosting text-based game servers, contact the author at // Stephen Dennis <sdennis@svdltd.com> for another license. // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include "db.h" #include "htab.h" #include "alloc.h" #include "mudconf.h" #include "svdhash.h" /* * --------------------------------------------------------------------------- * hashreset: Reset hash table stats. */ void hashreset(CHashTable *htab) { htab->ResetStats(); } #pragma pack(1) static struct { int *hashdata; char aTarget[LBUF_SIZE+125]; } htab_rec; #pragma pack() /* * --------------------------------------------------------------------------- * * hashfindLEN: Look up an entry in a hash table and return a pointer to its * * hash data. */ int *hashfindLEN(void *str, int nStr, CHashTable *htab) { if (str == NULL || nStr <= 0) return NULL; unsigned long nHash = CRC32_ProcessBuffer(0, str, nStr); HP_DIRINDEX iDir = HF_FIND_FIRST; iDir = htab->FindFirstKey(nHash); while (iDir != HF_FIND_END) { HP_HEAPLENGTH nRecord; htab->Copy(iDir, &nRecord, &htab_rec); int nTarget = nRecord - sizeof(int *); if (nTarget == nStr && memcmp(str, htab_rec.aTarget, nStr) == 0) { return htab_rec.hashdata; } iDir = htab->FindNextKey(iDir, nHash); } return NULL; } /* * --------------------------------------------------------------------------- * * hashaddLEN: Add a new entry to a hash table. */ int hashaddLEN(void *str, int nStr, int *hashdata, CHashTable *htab) { // Make sure that the entry isn't already in the hash table. If it // is, exit with an error. // if (str == NULL || nStr <= 0) return -1; unsigned long nHash = CRC32_ProcessBuffer(0, str, nStr); HP_DIRINDEX iDir = htab->FindFirstKey(nHash); while (iDir != HF_FIND_END) { HP_HEAPLENGTH nRecord; htab->Copy(iDir, &nRecord, &htab_rec); int nTarget = nRecord - sizeof(int *); if (nTarget == nStr && memcmp(str, htab_rec.aTarget, nStr) == 0) { return -1; } iDir = htab->FindNextKey(iDir, nHash); } // Otherwise, add it. // htab_rec.hashdata = hashdata; memcpy(htab_rec.aTarget, str, nStr); unsigned int nRecord = nStr + sizeof(int *); htab->Insert(nRecord, nHash, &htab_rec); return 0; } /* * --------------------------------------------------------------------------- * * hashdelete: Remove an entry from a hash table. */ void hashdeleteLEN(void *str, int nStr, CHashTable *htab) { if (str == NULL || nStr <= 0) return; unsigned long nHash = CRC32_ProcessBuffer(0, str, nStr); HP_DIRINDEX iDir = htab->FindFirstKey(nHash); while (iDir != HF_FIND_END) { HP_HEAPLENGTH nRecord; htab->Copy(iDir, &nRecord, &htab_rec); int nTarget = nRecord - sizeof(int *); if (nTarget == nStr && memcmp(str, htab_rec.aTarget, nStr) == 0) { htab->Remove(iDir); } iDir = htab->FindNextKey(iDir, nHash); } } /* * --------------------------------------------------------------------------- * * hashflush: free all the entries in a hashtable. */ void hashflush(CHashTable *htab) { htab->Reset(); } /* * --------------------------------------------------------------------------- * * hashreplLEN: replace the data part of a hash entry. */ int hashreplLEN(void *str, int nStr, int *hashdata, CHashTable *htab) { if (str == NULL || nStr <= 0) return 0; unsigned long nHash = CRC32_ProcessBuffer(0, str, nStr); HP_DIRINDEX iDir = htab->FindFirstKey(nHash); while (iDir != HF_FIND_END) { HP_HEAPLENGTH nRecord; htab->Copy(iDir, &nRecord, &htab_rec); int nTarget = nRecord - sizeof(int *); if (nTarget == nStr && memcmp(str, htab_rec.aTarget, nStr) == 0) { htab_rec.hashdata = hashdata; htab->Update(iDir, nRecord, &htab_rec); return 1; } iDir = htab->FindNextKey(iDir, nHash); } return 0; } void hashreplall(int *old, int *new0, CHashTable *htab) { HP_HEAPLENGTH nRecord; for (HP_DIRINDEX iDir = htab->FindFirst(&nRecord, &htab_rec); iDir != HF_FIND_END; iDir = htab->FindNext(&nRecord, &htab_rec)) { if (htab_rec.hashdata == old) { htab_rec.hashdata = new0; htab->Update(iDir, nRecord, &htab_rec); } } } /* * --------------------------------------------------------------------------- * * hashinfo: return an mbuf with hashing stats */ char *hashinfo(const char *tab_name, CHashTable *htab) { char *buff = alloc_mbuf("hashinfo"); unsigned int hashsize; int entries; int deletes; int scans; int hits; int checks; int max_scan; htab->GetStats(&hashsize, &entries, &deletes, &scans, &hits, &checks, &max_scan); sprintf(buff, "%-15s %5d %8d %8d %10d %10d %10d %4d", tab_name, hashsize, entries, deletes, scans, hits, checks, max_scan); return buff; } /* * Returns the key for the first hash entry in 'htab'. */ int *hash_firstentry(CHashTable *htab) { HP_HEAPLENGTH nRecord; HP_DIRINDEX iDir = htab->FindFirst(&nRecord, &htab_rec); if (iDir != HF_FIND_END) { return htab_rec.hashdata; } return NULL; } int *hash_nextentry(CHashTable *htab) { HP_HEAPLENGTH nRecord; HP_DIRINDEX iDir = htab->FindNext(&nRecord, &htab_rec); if (iDir != HF_FIND_END) { return htab_rec.hashdata; } return NULL; } char *hash_firstkey(CHashTable *htab, int *nKeyLength) { HP_HEAPLENGTH nRecord; HP_DIRINDEX iDir = htab->FindFirst(&nRecord, &htab_rec); if (iDir != HF_FIND_END) { *nKeyLength = nRecord-sizeof(int *); return htab_rec.aTarget; } *nKeyLength = 0; return NULL; } char *hash_nextkey(CHashTable *htab, int *nKeyLength) { HP_HEAPLENGTH nRecord; HP_DIRINDEX iDir = htab->FindNext(&nRecord, &htab_rec); if (iDir != HF_FIND_END) { *nKeyLength = nRecord-sizeof(int *); return htab_rec.aTarget; } *nKeyLength = 0; return NULL; } #ifndef STANDALONE /* * --------------------------------------------------------------------------- * * search_nametab: Search a name table for a match and return the flag value. */ int search_nametab(dbref player, NAMETAB *ntab, char *flagname) { NAMETAB *nt; for (nt = ntab; nt->name; nt++) { if (minmatch(flagname, nt->name, nt->minlen)) { if (check_access(player, nt->perm)) { return nt->flag; } else return -2; } } return -1; } /* * --------------------------------------------------------------------------- * * find_nametab_ent: Search a name table for a match and return a pointer to it. */ NAMETAB *find_nametab_ent(dbref player, NAMETAB *ntab, char *flagname) { NAMETAB *nt; for (nt = ntab; nt->name; nt++) { if (minmatch(flagname, nt->name, nt->minlen)) { if (check_access(player, nt->perm)) { return nt; } } } return NULL; } /* * --------------------------------------------------------------------------- * * display_nametab: Print out the names of the entries in a name table. */ void display_nametab(dbref player, NAMETAB *ntab, char *prefix, int list_if_none) { char *buf, *bp, *cp; NAMETAB *nt; int got_one; buf = alloc_lbuf("display_nametab"); bp = buf; got_one = 0; for (cp = prefix; *cp; cp++) *bp++ = *cp; for (nt = ntab; nt->name; nt++) { if (God(player) || check_access(player, nt->perm)) { *bp++ = ' '; for (cp = nt->name; *cp; cp++) *bp++ = *cp; got_one = 1; } } *bp = '\0'; if (got_one || list_if_none) notify(player, buf); free_lbuf(buf); } /* * --------------------------------------------------------------------------- * * interp_nametab: Print values for flags defined in name table. */ void interp_nametab(dbref player, NAMETAB *ntab, int flagword, char *prefix, char *true_text, char *false_text) { char *buf, *bp, *cp; NAMETAB *nt; buf = alloc_lbuf("interp_nametab"); bp = buf; for (cp = prefix; *cp; cp++) *bp++ = *cp; nt = ntab; while (nt->name) { if (God(player) || check_access(player, nt->perm)) { *bp++ = ' '; for (cp = nt->name; *cp; cp++) *bp++ = *cp; *bp++ = '.'; *bp++ = '.'; *bp++ = '.'; if ((flagword & nt->flag) != 0) cp = true_text; else cp = false_text; while (*cp) *bp++ = *cp++; if ((++nt)->name) *bp++ = ';'; } } *bp = '\0'; notify(player, buf); free_lbuf(buf); } /* * --------------------------------------------------------------------------- * * listset_nametab: Print values for flags defined in name table. */ void listset_nametab(dbref player, NAMETAB *ntab, int flagword, char *prefix, int list_if_none) { char *buf, *bp, *cp; NAMETAB *nt; int got_one; buf = bp = alloc_lbuf("listset_nametab"); for (cp = prefix; *cp; cp++) *bp++ = *cp; nt = ntab; got_one = 0; while (nt->name) { if (((flagword & nt->flag) != 0) && (God(player) || check_access(player, nt->perm))) { *bp++ = ' '; for (cp = nt->name; *cp; cp++) *bp++ = *cp; got_one = 1; } nt++; } *bp = '\0'; if (got_one || list_if_none) notify(player, buf); free_lbuf(buf); } /* * --------------------------------------------------------------------------- * * cf_ntab_access: Change the access on a nametab entry. */ extern void FDECL(cf_log_notfound, (dbref, char *, const char *, char *)); CF_HAND(cf_ntab_access) { NAMETAB *np; char *ap; for (ap = str; *ap && !Tiny_IsSpace[(unsigned char)*ap]; ap++) ; if (*ap) *ap++ = '\0'; while (Tiny_IsSpace[(unsigned char)*ap]) ap++; for (np = (NAMETAB *) vp; np->name; np++) { if (minmatch(str, np->name, np->minlen)) { return cf_modify_bits(&(np->perm), ap, extra, player, cmd); } } cf_log_notfound(player, cmd, "Entry", str); return -1; } #endif STANDALONE