On Thu, 4 Jan 2001, Brandon Allen wrote: > i was going to move all the weather text and most of the other commen > text in the mud out to text files in /lib/text so that it can be > changed on the fly and reloaded i have seen manny things in the mud > that i think it would be fun to have in a text file so that i could > throw random stuff into it. Moving the messages into a separately indexed file wouldn't be difficult. A general approach that would meet your specifications but not be overly flexible (that is, you couldn't use it to implement multi-language support in your Mud [that's what GNU gettext is for, anyway]) or difficult to implement would have the message file arranged as so: <string key>~ <string>~ . . . $~ This is easy to load using fread_string(). The file is over when you read $ as a string key. While reading the file, build a hash table from it using the string keys. The ELF hash function (taken from SVR4 binary file specifications several years ago) will work well enough for us: unsigned long hasher(const unsigned char *name) { unsigned long h = 0; unsigned long g; while (*name) { h = (h << 4) + *(name++); g = h & 0xF0000000; if (g) h ^= g >> 24; h &= ~g; } return h; } Now we write a function, "fetch_message()," which takes a string key, looks it up in the hash function, and returns the proper message (or an error string). E.g., const char *fetch_message(const unsigned char *key) { unsigned long k = hasher(key) % MESG_TABLE_SIZE; struct str_list_node *stri; for (stri = mesgHashTable[k]; stri; stri = stri->next) if (k == stri->key) break; if (!stri) { static char erbuf[MAX_STRING_LENGTH]; log("SYSERR: Invalid message key '%s'", key); sprintf(erbuf, "ERROR! Please report this message to an admin:\r\n" "Invalid message key '%s' requested.\r\n", key); return ((const char *) erbuf); } return ((const char *) stri->string); } As you can see, this is fairly simple. I envision the hash table as using linked lists for collision resolution. Building the hash table seems to be pretty simple: struct str_list_node { unsigned long key; char *string; struct str_list_node *next; }; /* * Only adjust MESG_TABLE_SIZE if you really understand hash tables and * why 67 is the specific number chosen. I chose it because it's a * prime number and, I think, high enough to prevent clustering and low * enough to not waste memory. Your opinion, and mileage, may vary. As * this is Mailer Code(tm), you might want to actually look into it to * ensure I'm not out of my bloody mind. */ #define MESG_TABLE_SIZE 67 struct str_list_node *mesgHashTable[MESG_TABLE_SIZE]; void init_message_hash(void) { int i; for (i = MESG_TABLE_SIZE-1; i >= 0; i--) mesgHashTable[i] = NULL; } /* Precondition: 'string' is an allocated string. */ void insert_message(const unsigned char *key, char *string) { unsigned long k = hasher(key) unsigned long idx = k % MESG_TABLE_SIZE; struct str_list_node *strn; CREATE(strn, struct str_list_node, 1); strn->key = k; strn->string = string; strn->next = mesgHashTable[idx]; mesgHashTable[idx] = strn; } Editing the message database is fairly simple, too, but I'll leave that as an exercise to the reader. I think the above method would fit all of your requirements and retain efficiency. -dak -- +---------------------------------------------------------------+ | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html | +---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/03/01 PST