Fix some corner cases, where partial matches would not be found.

git-svn-id: https://shellinabox.googlecode.com/svn/trunk@92 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
zodiac 2009-03-30 07:23:40 +00:00
parent 3edcc43298
commit c19ed2f3ca

View file

@ -169,48 +169,60 @@ void addToTrie(struct Trie *trie, const char *key, char *value) {
addLeafToTrie(newNode, *key, key + 1, len - 1, value); addLeafToTrie(newNode, *key, key + 1, len - 1, value);
} else { } else {
initTrie(newNode, trie->destructor, trie->arg); initTrie(newNode, trie->destructor, trie->arg);
trie->value = value; newNode->value = value;
} }
} }
} }
char *getFromTrie(const struct Trie *trie, const char *key, char **diff) { char *getFromTrie(const struct Trie *trie, const char *key, char **diff) {
if (diff) { if (diff) {
*diff = NULL; *diff = NULL;
} }
struct Trie *partial = NULL;
char *partialKey = NULL;
for (;;) { for (;;) {
if (trie->idx > 0) { if (trie->idx > 0) {
if (memcmp(trie->key, key, trie->idx)) { if (memcmp(trie->key, key, trie->idx)) {
if (diff) {
*diff = partialKey;
return partial->value;
}
return NULL; return NULL;
} }
key += trie->idx; key += trie->idx;
} }
int partial = -1;
for (int i = 0; ; i++) { for (int i = 0; ; i++) {
if (i >= trie->numChildren) { if (i >= trie->numChildren) {
if (diff && partial >= 0) { if (diff && partial != NULL) {
// If the caller provided a "diff" pointer, then we allow partial // If the caller provided a "diff" pointer, then we allow partial
// matches for the longest possible prefix that is a key in the // matches for the longest possible prefix that is a key in the
// trie. Upon return, the "diff" pointer points to the first // trie. Upon return, the "diff" pointer points to the first
// character in the key does not match. // character in the key does not match.
*diff = (char *)key; *diff = partialKey;
return trie->children[partial].value; return partial->value;
} }
return NULL; return NULL;
} else if (*key == trie->children[i].ch) { } else if (*key == trie->children[i].ch) {
if (!*key) { if (!*key) {
if (diff) { if (diff) {
*diff = (char *)key; *diff = (char *)key;
} }
return trie->children[i].value; return trie->children[i].value;
} }
for (int j = i + 1; j < trie->numChildren; j++) {
if (!trie->children[j].ch) {
partial = trie->children + j;
partialKey = (char *)key;
break;
}
}
trie = &trie->children[i]; trie = &trie->children[i];
key++; key++;
break; break;
} else if (!trie->children[i].ch) { } else if (!trie->children[i].ch) {
partial = i; partial = trie->children + i;
partialKey = (char *)key;
} }
} }
} }
} }