diff options
Diffstat (limited to 'src/rb3str.c')
| -rw-r--r-- | src/rb3str.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/src/rb3str.c b/src/rb3str.c index f4c16fa..367ff83 100644 --- a/src/rb3str.c +++ b/src/rb3str.c @@ -60,32 +60,37 @@ teco_rb3str_find(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar return (teco_rb3str_head_t *)rb3_find(tree, cmp, &data); } -/** @memberof teco_rb3str_tree_t */ -teco_rb3str_head_t * -teco_rb3str_nfind(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar *str, gsize len) +/* + * This is based on rb3_INLINE_find() in rb3ptr.h. + * FIXME: Should perhaps be in rb3ptr.c. + */ +struct rb3_head * +rb3_nfind(struct rb3_tree *tree, rb3_cmp cmp, void *data) { - rb3_cmp *cmp = case_sensitive ? (rb3_cmp *)teco_rb3str_cmp : (rb3_cmp *)teco_rb3str_casecmp; - teco_string_t data = {(gchar *)str, len}; - - /* - * This is based on rb3_INLINE_find() in rb3ptr.h. - * Alternatively, we might adapt/wrap teco_rb3str_cmp() in order to store - * the last element > data. - */ struct rb3_head *parent = rb3_get_base(tree); struct rb3_head *res = NULL; int dir = RB3_LEFT; + while (rb3_has_child(parent, dir)) { parent = rb3_get_child(parent, dir); - int r = cmp(parent, &data); + int r = cmp(parent, data); if (r == 0) - return (teco_rb3str_head_t *)parent; - dir = (r < 0) ? RB3_RIGHT : RB3_LEFT; + return parent; + dir = r < 0 ? RB3_RIGHT : RB3_LEFT; if (dir == RB3_LEFT) res = parent; } - return (teco_rb3str_head_t *)res; + return res; +} + +/** @memberof teco_rb3str_tree_t */ +teco_rb3str_head_t * +teco_rb3str_nfind(teco_rb3str_tree_t *tree, gboolean case_sensitive, const gchar *str, gsize len) +{ + rb3_cmp *cmp = case_sensitive ? (rb3_cmp *)teco_rb3str_cmp : (rb3_cmp *)teco_rb3str_casecmp; + teco_string_t data = {(gchar *)str, len}; + return (teco_rb3str_head_t *)rb3_nfind(tree, cmp, &data); } /** @@ -133,9 +138,14 @@ teco_rb3str_auto_complete(teco_rb3str_tree_t *tree, gboolean case_sensitive, if (prefix_len > 0) { teco_string_init(insert, first->key.data + str_len, prefix_len); } else if (prefixed_entries > 1) { + teco_rb3str_head_t *next; for (teco_rb3str_head_t *cur = first; cur && cur->key.len >= str_len && diff(cur->key, str, str_len) == str_len; - cur = teco_rb3str_get_next(cur)) { + cur = next) { + next = teco_rb3str_get_next(cur); + if (next && !teco_string_cmp(next->key, cur->key.data, cur->key.len)) + /* filter out duplicates */ + continue; if (restrict_len && g_utf8_strlen(cur->key.data, cur->key.len) != restrict_len) continue; |
