Files
strans/dict.c
Hojun-Cho 5faefd9a87 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.
2026-08-17 01:31:51 +09:00

91 lines
1.7 KiB
C

#include "dat.h"
#include "fn.h"
/* Appends the space-separated words of a node's entry to out[], up to max. */
static int
words(Tnode *nd, Str *out, int n, int max)
{
char *p, *e, *sp;
Str tmp;
if(nd->val == nil)
return n;
p = nd->val;
e = p + nd->vlen;
while(n < max && p < e){
while(p < e && *p == ' ')
p++;
sp = p;
while(p < e && *p != ' ')
p++;
if(sinit(&tmp, sp, p - sp) && tmp.n > 0)
out[n++] = tmp;
}
return n;
}
/* The entries at and below a node, in the dictionary's order. */
static int
below(Trie *t, int ni, Str *out, int n, int max)
{
Tnode *nd;
int ci;
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 words of its entry. */
int
dictlookup(Trie *t, Str *key, Str *out, int max)
{
int ni;
ni = key->n == 0 ? -1 : trienode(t, key);
if(ni < 0)
return 0;
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*
langopen(char *dir, char *name, char *ext)
{
char *path;
Trie *t;
path = smprint("%s/%s.%s", dir, name, ext);
if(path == nil)
die("out of memory");
t = trieopen(path);
free(path);
return t;
}
void
langinit(char *dir)
{
Lang *l;
for(l = langs; l < langs + nlang; l++){
if(l->mapname != nil)
l->map = langopen(dir, l->mapname, "map");
if(l->dictname != nil)
l->dict = langopen(dir, l->dictname, "dict");
}
}