1 #include <stdlib.h> /* bsearch */
2 #include <stdio.h> /* fprintf to stderr */
3 #include <string.h> /* strcmp */
4
5 #include "findtok.h"
6
7 /* This function fills in a structure of type token_list_t based on a token_t
8 array. The token_list_t structure contains some internal control data used
9 by find_token. The last element of the token_t array must have a NULL
10 pointer in the "token" field.
11
12 The main function of this function is to a) count the number of tokens and b)
13 make sure that the array of tokens that the programmer supplies
14 to us is sorted so that we can later use bsearch on it.
15
16 If the array is not sorted, we simply print a warning to stderr.
17 We do NOT resort the array in this case, because normally the
18 order of magnitude of keywords in this array is in the same order
19 of magnitude of keywords that will be in the config file to
20 parse, so that sorting of the array of the program start would
21 not yield any net performance gain. The programmer should supply
22 us with an already sorted list of keywords instead!
23 */
24
make_token_list(token_list_t * dst,token_t * src)25 void make_token_list (token_list_t *dst, token_t *src)
26 {
27 int i;
28
29 dst->tokens = src; dst->ntokens = 0; dst->bsearchable = 1;
30
31 if (src[0].token == NULL)
32 return; /* nothing to do for an empty list */
33
34 for (i = 1; src[i].token != NULL; i++)
35 {
36 if (dst->bsearchable && strcmp(src[i-1].token, src[i].token) >= 0)
37 {
38 fprintf (stderr, "Warning: Token array is not bsearchable. This "
39 "will result in a performance\npenalty. The offending "
40 "token is: %s\n", src[i].token);
41 dst->bsearchable = 0;
42 }
43 }
44
45 dst->ntokens = i;
46 }
47
token_compare(const void * a,const void * b)48 static int token_compare (const void *a, const void *b)
49 {
50 const token_t *pa = (const token_t *)a;
51 const token_t *pb = (const token_t *)b;
52
53 return strcmp(pa->token, pb->token);
54 }
55
56
57 /* This function returns the token ID based on a keyword, or -1 or
58 the keyword is not found in the token list. */
59
find_token(token_list_t * tokenlist,const char * key)60 int find_token(token_list_t *tokenlist, const char *key)
61 {
62 int i;
63 token_t keytoken, *result;
64
65 /* fall back code when the array is not
66 sorted */
67 if (!tokenlist->bsearchable)
68 {
69 for (i = 0; i < tokenlist->ntokens; i++)
70 {
71 if (!strcmp(tokenlist->tokens[i].token, key))
72 return tokenlist->tokens[i].id;
73 }
74 return -1;
75 }
76 /* bsearch code */
77 keytoken.token = key;
78 keytoken.id = -1;
79
80 result = bsearch(&keytoken, tokenlist->tokens, tokenlist->ntokens,
81 sizeof(token_t), token_compare);
82
83 if (result == NULL)
84 return -1;
85
86 return result->id;
87 }
88
89 #if 0
90
91 /* This code is an example on how to use the routines from this file */
92
93 #include "findtok.h"
94
95 enum { ID_LINK=0, ID_LOGFILE, ID_NODELIST, ID_SYSOP };
96
97 token_t mytokens[]=
98 {
99 { "link", ID_LINK },
100 { "logfile", ID_LOGFILE },
101 { "nodelist", ID_NODELIST },
102 { "sysop", ID_SYSOP },
103 { NULL, -1 }
104 };
105
106 token_list_t mytokenlist;
107
108 int main(void)
109 {
110 make_token_list(&mytokenlist, mytokens);
111 switch (find_token(&mytokenlist, "logfile"))
112 {
113 case ID_LINK: printf ("link\n"); break;
114 case ID_LOGFILE: printf ("logfile\n"); break;
115 case ID_NODELIST: printf ("nodelist\n"); break;
116 case ID_SYSOP: printf ("sysop\n"); break;
117 default: printf ("unknown keyword\n");
118 }
119 return 0;
120 }
121
122 #endif
123