* Search a trie for some key. Find the longest /-or-\0-terminated * prefix of the key for which the trie contains a value. If there is * no such prefix, return -1. Otherwise call fn with the unmatched * portion of the key and the found value. If fn returns 0 or * positive, then return its return value. If fn returns negative, * then call fn with the next-longest /-terminated prefix of th
| 262 | * |--------------------|----------------|------------------|--------------| |
| 263 | */ |
| 264 | static int trie_find(struct trie *root, const char *key, match_fn fn, |
| 265 | void *baton) |
| 266 | { |
| 267 | int i; |
| 268 | int result; |
| 269 | struct trie *child; |
| 270 | |
| 271 | if (!*key) { |
| 272 | /* we have reached the end of the key */ |
| 273 | if (root->value && !root->len) |
| 274 | return fn(key, root->value, baton); |
| 275 | else |
| 276 | return -1; |
| 277 | } |
| 278 | |
| 279 | for (i = 0; i < root->len; i++) { |
| 280 | /* Partial path normalization: skip consecutive slashes. */ |
| 281 | if (key[i] == '/' && key[i+1] == '/') { |
| 282 | key++; |
| 283 | continue; |
| 284 | } |
| 285 | if (root->contents[i] != key[i]) |
| 286 | return -1; |
| 287 | } |
| 288 | |
| 289 | /* Matched the entire compressed section */ |
| 290 | key += i; |
| 291 | if (!*key) { |
| 292 | /* End of key */ |
| 293 | if (root->value) |
| 294 | return fn(key, root->value, baton); |
| 295 | else |
| 296 | return -1; |
| 297 | } |
| 298 | |
| 299 | /* Partial path normalization: skip consecutive slashes */ |
| 300 | while (key[0] == '/' && key[1] == '/') |
| 301 | key++; |
| 302 | |
| 303 | child = root->children[(unsigned char)*key]; |
| 304 | if (child) |
| 305 | result = trie_find(child, key + 1, fn, baton); |
| 306 | else |
| 307 | result = -1; |
| 308 | |
| 309 | if (result >= 0 || (*key != '/' && *key != 0)) |
| 310 | return result; |
| 311 | if (root->value) |
| 312 | return fn(key, root->value, baton); |
| 313 | else |
| 314 | return -1; |
| 315 | } |
| 316 | |
| 317 | static struct trie common_trie; |
| 318 | static int common_trie_done_setup; |