tri: fix autocomplete when one string is a prefix of another
Also add a bunch of unit tests for all of the various tri functions. Signed-off-by: Max Regan <mgregan2@gmail.com>
This commit is contained in:
@@ -54,12 +54,71 @@ static void test_tri_prefix_match(void)
|
|||||||
tri_free(&tri);
|
tri_free(&tri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_tri_autocomplete(void)
|
||||||
|
{
|
||||||
|
struct tri tri;
|
||||||
|
bool ambiguous;
|
||||||
|
|
||||||
|
tri_init(&tri);
|
||||||
|
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, "pr", TO_PTR(1)), ==, 0);
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, "pref", TO_PTR(2)), ==, 0);
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, "Z", TO_PTR(3)), ==, 0);
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, "prefix", TO_PTR(4)), ==, 0);
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, "blah", TO_PTR(5)), ==, 0);
|
||||||
|
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "p", &ambiguous));
|
||||||
|
g_assert_true(ambiguous);
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "pr", &ambiguous));
|
||||||
|
g_assert_true(ambiguous);
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "pre", &ambiguous));
|
||||||
|
g_assert_true(ambiguous);
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "pref", &ambiguous));
|
||||||
|
g_assert_true(ambiguous);
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "prefix10", &ambiguous));
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
g_assert_null(tri_get_string_autocomplete(&tri, "asdfasdf", &ambiguous));
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "bla", &ambiguous)), ==, 5);
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefi", &ambiguous)), ==, 4);
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefix", &ambiguous)), ==, 4);
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "Z", &ambiguous)), ==, 3);
|
||||||
|
g_assert_false(ambiguous);
|
||||||
|
|
||||||
|
tri_free(&tri);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_tri_null(void)
|
||||||
|
{
|
||||||
|
struct tri tri;
|
||||||
|
|
||||||
|
tri_init(&tri);
|
||||||
|
|
||||||
|
g_assert_cmpint(tri_add_string(&tri, NULL, TO_PTR(1)), ==, -1);
|
||||||
|
g_assert_null(tri_prefix_match(&tri, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
g_test_init(&argc, &argv, NULL);
|
g_test_init(&argc, &argv, NULL);
|
||||||
|
|
||||||
g_test_add_func("/tri/get_string", test_tri_get_string);
|
g_test_add_func("/tri/get_string", test_tri_get_string);
|
||||||
g_test_add_func("/tri/prefix_match", test_tri_prefix_match);
|
g_test_add_func("/tri/prefix_match", test_tri_prefix_match);
|
||||||
|
g_test_add_func("/tri/autocomplete", test_tri_autocomplete);
|
||||||
|
g_test_add_func("/tri/null", test_tri_null);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/tri.c
17
src/tri.c
@@ -115,23 +115,28 @@ void *tri_get_string_autocomplete(struct tri *tri, const char *string, bool *amb
|
|||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
struct tri_node *next_node = NULL;
|
struct tri_node *next_node = NULL;
|
||||||
|
int num_paths = 0;
|
||||||
for (j = 0; j < ARRAY_SIZE(node->nodes); j++) {
|
for (j = 0; j < ARRAY_SIZE(node->nodes); j++) {
|
||||||
|
if (node->nodes[j] != NULL) {
|
||||||
if (node->nodes[j] != NULL && next_node == NULL) {
|
|
||||||
next_node = node->nodes[j];
|
next_node = node->nodes[j];
|
||||||
} else if (node->nodes[j] != NULL && next_node != NULL) {
|
num_paths++;
|
||||||
*ambiguous = true;
|
if (num_paths > 1) {
|
||||||
return NULL;
|
*ambiguous = true;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_node == NULL) {
|
if (next_node == NULL) {
|
||||||
return node->value;
|
return node->value;
|
||||||
|
} else if (node->value != NULL && next_node != NULL) {
|
||||||
|
*ambiguous = true;
|
||||||
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
node = next_node;
|
node = next_node;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return node->value;
|
return node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user