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:
parent
3edcc43298
commit
c19ed2f3ca
1 changed files with 22 additions and 10 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue