Our system needs to accept user input from a terminal and match against a few known keyword strings (maybe 10).
We don’t have the space/computrons to do regexp etc., code needs to be tiny & quick.
Now, the nasty way to do this is:
// str is null-terminated, assume we know it's safe/sane here
if(!strncmp(str,"hello",5)
{
do_hello();
}
else if(!strncmp(str,"world",5)
{
do_world();
}
else
{
meh(); // Wasn't a match
}
So, after a bit of googling & reading I’m being convinced that a nicer way is to pre-compute the hash of the various matches as an int, and then just use a case statement:
// Assume hash() stops at NULL
switch(hash(str))
{
case HASH_OF_HELLO:
do_hello();
break;
case HASH_OF_WORLD:
do_world();
break;
default:
meh();
break;
}
We can compute the *HASH_OF_match* at compile time. This seems potentially a faster / more elegant way to pick a string from a relatively small set.
So – does this seem reasonable? / Is there a glaring problem with doing this? / Anyone got a more elegant way of doing it?
As a footnote, this is the nicest looking hash algorithm I’ve seen this afternoon ;), credited to dan bernstein, it looks up to the job at hand.
unsigned int
get_hash(const char* s)
{
unsigned int hash = 0;
int c;
while((c = *s++))
{
// hash = hash * 33 ^ c
hash = ((hash << 5) + hash) ^ c;
}
return hash;
}
The problem with hashing is that an arbitrary string entered by the user may generate the same hash as one of your matches and you’ll execute the wrong stuff. For a search set as small as 10 I’d just stick to the
if-elseapproach. Or use a string array and function pointer array (assuming all functions have the same signature) to select the function to execute.