dict: lookups take a trie; a prefix search is its own function; no self-key rule

dictlookup took a Lang for two reasons that were not its business: to
know whether to walk below the key (the emoji dictionary) and to drop a
candidate equal to the key except there.  No dictionary lists its key
among its candidates — the rule was left from a first version that put
the reading first itself — so it goes, and the walk is dictprefix(),
called by the emoji search alone.
This commit is contained in:
2026-08-17 01:31:51 +09:00
parent 3d862bdc0d
commit 5faefd9a87
6 changed files with 59 additions and 51 deletions

46
dict.c
View File

@@ -1,13 +1,9 @@
#include "dat.h"
#include "fn.h"
/*
* Appends the space-separated words of a node's entry to out[], up to
* max: its candidates, minus the key itself, except in the emoji
* dictionary, where a query may name its own answer.
*/
/* Appends the space-separated words of a node's entry to out[], up to max. */
static int
words(Lang *l, Str *key, Tnode *nd, Str *out, int n, int max)
words(Tnode *nd, Str *out, int n, int max)
{
char *p, *e, *sp;
Str tmp;
@@ -22,8 +18,7 @@ words(Lang *l, Str *key, Tnode *nd, Str *out, int n, int max)
sp = p;
while(p < e && *p != ' ')
p++;
if(sinit(&tmp, sp, p - sp) && tmp.n > 0 &&
(l->lang == LangEMOJI || scmp(&tmp, key) != 0))
if(sinit(&tmp, sp, p - sp) && tmp.n > 0)
out[n++] = tmp;
}
return n;
@@ -31,33 +26,40 @@ words(Lang *l, Str *key, Tnode *nd, Str *out, int n, int max)
/* The entries at and below a node, in the dictionary's order. */
static int
below(Lang *l, Str *key, int ni, Str *out, int n, int max)
below(Trie *t, int ni, Str *out, int n, int max)
{
Tnode *nd;
int ci;
nd = &l->dict->nodes[ni];
n = words(l, key, nd, out, n, max);
for(ci = nd->child; ci >= 0 && n < max; ci = l->dict->nodes[ci].sibling)
n = below(l, key, ci, out, n, max);
nd = &t->nodes[ni];
n = words(nd, out, n, max);
for(ci = nd->child; ci >= 0 && n < max; ci = t->nodes[ci].sibling)
n = below(t, ci, out, n, max);
return n;
}
/*
* Fills out[] with up to max candidates for key. The emoji dictionary is
* searched by prefix, the key's own entry first; the others exactly.
*/
/* Fills out[] with up to max candidates for key: the words of its entry. */
int
dictlookup(Lang *l, Str *key, Str *out, int max)
dictlookup(Trie *t, Str *key, Str *out, int max)
{
int ni;
ni = key->n == 0 ? -1 : trienode(l->dict, key);
ni = key->n == 0 ? -1 : trienode(t, key);
if(ni < 0)
return 0;
if(l->lang == LangEMOJI)
return below(l, key, ni, out, 0, max);
return words(l, key, &l->dict->nodes[ni], out, 0, max);
return words(&t->nodes[ni], out, 0, max);
}
/* As dictlookup, for every entry key is a prefix of, key's own first. */
int
dictprefix(Trie *t, Str *key, Str *out, int max)
{
int ni;
ni = key->n == 0 ? -1 : trienode(t, key);
if(ni < 0)
return 0;
return below(t, ni, out, 0, max);
}
static Trie*