6 #define DHASH(d, s) ((d)->level2 && (s)[0] ? (((unsigned char) (s)[1]) << 8) | (unsigned char) (s)[0] : (unsigned char) s[0])
7 #define CNTMIN (1 << 10)
15 int notfound
; /* the value returned for missing keys */
16 int level2
; /* use two characters for hashing */
17 int dupkeys
; /* duplicate keys if set */
20 static void dict_extend(struct dict
*d
, int size
)
22 d
->key
= mextend(d
->key
, d
->size
, size
, sizeof(d
->key
[0]));
23 d
->val
= mextend(d
->val
, d
->size
, size
, sizeof(d
->val
[0]));
28 * initialise a dictionary
30 * notfound: the value returned for missing keys.
31 * dupkeys: if nonzero, store a copy of keys inserted via dict_put().
32 * level2: use two characters for hasing
34 struct dict
*dict_make(int notfound
, int dupkeys
, int level2
)
36 struct dict
*d
= xmalloc(sizeof(*d
));
37 memset(d
, 0, sizeof(*d
));
41 d
->notfound
= notfound
;
43 dict_extend(d
, CNTMIN
);
47 void dict_free(struct dict
*d
)
51 for (i
= 0; i
< d
->size
; i
++)
59 void dict_put(struct dict
*d
, char *key
, int val
)
63 dict_extend(d
, d
->n
+ CNTMIN
);
65 int len
= strlen(key
) + 1;
66 char *dup
= xmalloc(len
);
67 memcpy(dup
, key
, len
);
73 iset_put(d
->map
, DHASH(d
, key
), idx
);
76 /* return the index of key in d */
77 int dict_idx(struct dict
*d
, char *key
)
79 int h
= DHASH(d
, key
);
80 int *b
= iset_get(d
->map
, h
);
81 int *r
= b
+ iset_len(d
->map
, h
);
83 if (!strcmp(d
->key
[*r
], key
))
88 char *dict_key(struct dict
*d
, int idx
)
93 int dict_val(struct dict
*d
, int idx
)
98 int dict_get(struct dict
*d
, char *key
)
100 int idx
= dict_idx(d
, key
);
101 return idx
>= 0 ? d
->val
[idx
] : d
->notfound
;
104 /* match a prefix of key; in the first call, *idx should be -1 */
105 int dict_prefix(struct dict
*d
, char *key
, int *pos
)
107 int *r
= iset_get(d
->map
, DHASH(d
, key
));
108 while (r
&& r
[++*pos
] >= 0) {
110 int plen
= strlen(d
->key
[idx
]);
111 if (!strncmp(d
->key
[idx
], key
, plen
))