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:
46
dict.c
46
dict.c
@@ -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*
|
||||
|
||||
3
fn.h
3
fn.h
@@ -21,7 +21,8 @@ int trielookup(Trie*, Str*, char**, int*);
|
||||
Lang* getlang(int);
|
||||
void langinit(char*);
|
||||
|
||||
int dictlookup(Lang*, Str*, Str*, int);
|
||||
int dictlookup(Trie*, Str*, Str*, int);
|
||||
int dictprefix(Trie*, Str*, Str*, int);
|
||||
|
||||
void drawthread(void*);
|
||||
void popuparea(Area*, int, Area*, int, int, Area*);
|
||||
|
||||
12
strans.c
12
strans.c
@@ -289,7 +289,7 @@ dictqokuri(Str *reading)
|
||||
key = *reading;
|
||||
key.n = i;
|
||||
sputr(&key, c);
|
||||
n = dictlookup(im.l, &key, kouho, Maxkouho);
|
||||
n = dictlookup(im.l->dict, &key, kouho, Maxkouho);
|
||||
sclear(&okuri);
|
||||
for(j = i - (reading->r[i-1] == L'っ'); j < reading->n; j++)
|
||||
sputr(&okuri, reading->r[j]);
|
||||
@@ -310,7 +310,7 @@ dictqjp(void)
|
||||
if(!isjp(&im) || !jpreading(im.l->map, &im.pre, &im.raw, &reading) ||
|
||||
reading.n == 0)
|
||||
return;
|
||||
im.nkouho = dictlookup(im.l, &reading, im.kouho, Maxkouho);
|
||||
im.nkouho = dictlookup(im.l->dict, &reading, im.kouho, Maxkouho);
|
||||
dictqokuri(&reading);
|
||||
}
|
||||
|
||||
@@ -572,13 +572,13 @@ emojiquery(void)
|
||||
transstr(im.l, nil, &search.raw, &local);
|
||||
foldascii(&local);
|
||||
clearkouho();
|
||||
n = dictlookup(getlang(LangEMOJI), &raw, kouho, Maxkouho);
|
||||
n = dictprefix(getlang(LangEMOJI)->dict, &raw, kouho, Maxkouho);
|
||||
rawhit = n != 0;
|
||||
for(i = 0; i < n; i++)
|
||||
addkouho(&kouho[i]);
|
||||
localhit = 0;
|
||||
if(scmp(&raw, &local) != 0){
|
||||
n = dictlookup(getlang(LangEMOJI), &local, kouho, Maxkouho);
|
||||
n = dictprefix(getlang(LangEMOJI)->dict, &local, kouho, Maxkouho);
|
||||
localhit = n != 0;
|
||||
for(i = 0; i < n; i++)
|
||||
addkouho(&kouho[i]);
|
||||
@@ -593,8 +593,8 @@ hanjaquery(void)
|
||||
{
|
||||
transstr(im.l, &search.seed, &search.raw, &search.text);
|
||||
clearkouho();
|
||||
im.nkouho = dictlookup(getlang(LangHANJA), &search.text, im.kouho,
|
||||
Maxkouho);
|
||||
im.nkouho = dictlookup(getlang(LangHANJA)->dict, &search.text,
|
||||
im.kouho, Maxkouho);
|
||||
selectfirst();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ dictionary_candidates(struct ct *t)
|
||||
lang = getlang(LangJP);
|
||||
saved = lang->dict;
|
||||
lang->dict = trienew();
|
||||
trieput(lang->dict, "かな", strlen("かな"), " 候補1 かな 候補2 ",
|
||||
strlen(" 候補1 かな 候補2 "));
|
||||
trieput(lang->dict, "かな", strlen("かな"), " 候補1 候補2 ",
|
||||
strlen(" 候補1 候補2 "));
|
||||
key = mkstr("かな");
|
||||
n = dictlookup(lang, &key, kouho, Maxkouho);
|
||||
n = dictlookup(lang->dict, &key, kouho, Maxkouho);
|
||||
if(CT_EQ_INT(t, 2, n)){
|
||||
checkstr(t, "candidate 1", "候補1", &kouho[0]);
|
||||
checkstr(t, "candidate 2", "候補2", &kouho[1]);
|
||||
@@ -34,13 +34,13 @@ dictionary_candidates(struct ct *t)
|
||||
*p = '\0';
|
||||
trieput(lang->dict, "key", 3, many, strlen(many));
|
||||
key = mkstr("key");
|
||||
n = dictlookup(lang, &key, kouho, Maxkouho);
|
||||
n = dictlookup(lang->dict, &key, kouho, Maxkouho);
|
||||
if(CT_EQ_INT(t, Maxkouho, n)){
|
||||
checkstr(t, "first capped candidate", "c00", &kouho[0]);
|
||||
snprint(item, sizeof item, "c%02d", Maxkouho-1);
|
||||
checkstr(t, "last capped candidate", item, &kouho[Maxkouho-1]);
|
||||
}
|
||||
CT_EQ_INT(t, 3, dictlookup(lang, &key, kouho, 3));
|
||||
CT_EQ_INT(t, 3, dictlookup(lang->dict, &key, kouho, 3));
|
||||
trieclose(lang->dict);
|
||||
lang->dict = saved;
|
||||
}
|
||||
@@ -56,28 +56,33 @@ dictionary_misses(struct ct *t)
|
||||
saved = lang->dict;
|
||||
lang->dict = trienew();
|
||||
key = mkstr("");
|
||||
CT_EQ_INT(t, 0, dictlookup(lang, &key, kouho, Maxkouho));
|
||||
CT_EQ_INT(t, 0, dictlookup(lang->dict, &key, kouho, Maxkouho));
|
||||
key = mkstr("missing");
|
||||
CT_EQ_INT(t, 0, dictlookup(lang, &key, kouho, Maxkouho));
|
||||
CT_EQ_INT(t, 0, dictlookup(getlang(LangKO), &key, kouho, Maxkouho));
|
||||
CT_EQ_INT(t, 0, dictlookup(lang->dict, &key, kouho, Maxkouho));
|
||||
CT_EQ_INT(t, 0, dictlookup(getlang(LangKO)->dict, &key, kouho, Maxkouho));
|
||||
trieclose(lang->dict);
|
||||
lang->dict = saved;
|
||||
}
|
||||
|
||||
void
|
||||
dictionary_emoji_identity(struct ct *t)
|
||||
dictionary_prefix(struct ct *t)
|
||||
{
|
||||
Str kouho[Maxkouho], key;
|
||||
Trie *saved;
|
||||
Lang *lang;
|
||||
Trie *dict;
|
||||
|
||||
lang = getlang(LangEMOJI);
|
||||
saved = lang->dict;
|
||||
lang->dict = trienew();
|
||||
trieput(lang->dict, "é", strlen("é"), "é", strlen("é"));
|
||||
key = mkstr("é");
|
||||
if(CT_EQ_INT(t, 1, dictlookup(lang, &key, kouho, Maxkouho)))
|
||||
checkstr(t, "emoji identity candidate", "é", &kouho[0]);
|
||||
trieclose(lang->dict);
|
||||
lang->dict = saved;
|
||||
dict = trienew();
|
||||
trieput(dict, "smile", 5, "A B", 3);
|
||||
trieput(dict, "smiley", 6, "B C", 3);
|
||||
trieput(dict, "sad", 3, "D", 1);
|
||||
key = mkstr("smile");
|
||||
if(CT_EQ_INT(t, 4, dictprefix(dict, &key, kouho, Maxkouho))){
|
||||
checkstr(t, "own entry first", "A", &kouho[0]);
|
||||
checkstr(t, "entry below", "C", &kouho[3]);
|
||||
}
|
||||
key = mkstr("s");
|
||||
CT_EQ_INT(t, 5, dictprefix(dict, &key, kouho, Maxkouho));
|
||||
CT_EQ_INT(t, 2, dictprefix(dict, &key, kouho, 2));
|
||||
key = mkstr("x");
|
||||
CT_EQ_INT(t, 0, dictprefix(dict, &key, kouho, Maxkouho));
|
||||
trieclose(dict);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ void engine_randomized_stress(struct ct*);
|
||||
void engine_full_boundary_passthrough(struct ct*);
|
||||
void dictionary_candidates(struct ct*);
|
||||
void dictionary_misses(struct ct*);
|
||||
void dictionary_emoji_identity(struct ct*);
|
||||
void dictionary_prefix(struct ct*);
|
||||
void ipc_masks_modifiers(struct ct*);
|
||||
void ipc_control_and_caret_frames(struct ct*);
|
||||
void ipc_runtime_path(struct ct*);
|
||||
|
||||
@@ -118,7 +118,7 @@ static const struct ct_test tests[] = {
|
||||
{ "engine/full-boundary-passthrough", engine_full_boundary_passthrough },
|
||||
{ "dict/candidates", dictionary_candidates },
|
||||
{ "dict/misses", dictionary_misses },
|
||||
{ "dict/emoji-identity", dictionary_emoji_identity },
|
||||
{ "dict/prefix", dictionary_prefix },
|
||||
{ "ipc/masks-modifiers", ipc_masks_modifiers },
|
||||
{ "ipc/control-caret-frames", ipc_control_and_caret_frames },
|
||||
{ "ipc/runtime-path", ipc_runtime_path },
|
||||
|
||||
Reference in New Issue
Block a user