#include /* bsearch */ #include /* fprintf to stderr */ #include /* strcmp */ #include "findtok.h" /* This function fills in a structure of type token_list_t based on a token_t array. The token_list_t structure contains some internal control data used by find_token. The last element of the token_t array must have a NULL pointer in the "token" field. The main function of this function is to a) count the number of tokens and b) make sure that the array of tokens that the programmer supplies to us is sorted so that we can later use bsearch on it. If the array is not sorted, we simply print a warning to stderr. We do NOT resort the array in this case, because normally the order of magnitude of keywords in this array is in the same order of magnitude of keywords that will be in the config file to parse, so that sorting of the array of the program start would not yield any net performance gain. The programmer should supply us with an already sorted list of keywords instead! */ void make_token_list (token_list_t *dst, token_t *src) { int i; dst->tokens = src; dst->ntokens = 0; dst->bsearchable = 1; if (src[0].token == NULL) return; /* nothing to do for an empty list */ for (i = 1; src[i].token != NULL; i++) { if (dst->bsearchable && strcmp(src[i-1].token, src[i].token) >= 0) { fprintf (stderr, "Warning: Token array is not bsearchable. This " "will result in a performance\npenalty. The offending " "token is: %s\n", src[i].token); dst->bsearchable = 0; } } dst->ntokens = i; } static int token_compare (const void *a, const void *b) { const token_t *pa = (const token_t *)a; const token_t *pb = (const token_t *)b; return strcmp(pa->token, pb->token); } /* This function returns the token ID based on a keyword, or -1 or the keyword is not found in the token list. */ int find_token(token_list_t *tokenlist, const char *key) { int i; token_t keytoken, *result; /* fall back code when the array is not sorted */ if (!tokenlist->bsearchable) { for (i = 0; i < tokenlist->ntokens; i++) { if (!strcmp(tokenlist->tokens[i].token, key)) return tokenlist->tokens[i].id; } return -1; } /* bsearch code */ keytoken.token = key; keytoken.id = -1; result = bsearch(&keytoken, tokenlist->tokens, tokenlist->ntokens, sizeof(token_t), token_compare); if (result == NULL) return -1; return result->id; } #if 0 /* This code is an example on how to use the routines from this file */ #include "findtok.h" enum { ID_LINK=0, ID_LOGFILE, ID_NODELIST, ID_SYSOP }; token_t mytokens[]= { { "link", ID_LINK }, { "logfile", ID_LOGFILE }, { "nodelist", ID_NODELIST }, { "sysop", ID_SYSOP }, { NULL, -1 } }; token_list_t mytokenlist; int main(void) { make_token_list(&mytokenlist, mytokens); switch (find_token(&mytokenlist, "logfile")) { case ID_LINK: printf ("link\n"); break; case ID_LOGFILE: printf ("logfile\n"); break; case ID_NODELIST: printf ("nodelist\n"); break; case ID_SYSOP: printf ("sysop\n"); break; default: printf ("unknown keyword\n"); } return 0; } #endif