The hash map served a single exact-match lookup that the trie already answers, at the price of a second container, a second file loader with its own drift, and a Str-to-UTF-8 conversion on every chain probe. The files are small (kanji.dict is 7.5k lines), so the trie holds both. trieopen validates keys and each space-separated value word against Str and reports path:line; trielookup takes the Str every caller holds and treats a nil trie as an unloaded map; trienew/trieput exist for tests. The overflow guards on growth, Trie.root (always 0) and the per-language init loop written twice are gone.
78 lines
1.4 KiB
C
78 lines
1.4 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
/* Candidates are the space-separated words of the value; the reading itself
|
|
* is a candidate only for the emoji dictionary. */
|
|
void
|
|
dictlookup(Dictreq *req, Dictres *res)
|
|
{
|
|
Lang *l;
|
|
char *p, *e, *sp;
|
|
Str tmp;
|
|
int vlen;
|
|
|
|
res->key = req->pre;
|
|
res->nkouho = 0;
|
|
res->lang = req->lang;
|
|
res->seq = req->seq;
|
|
l = getlang(req->lang);
|
|
if(req->key.n == 0 || l == nil ||
|
|
trielookup(l->dict, &req->key, &p, &vlen) != TrieExact)
|
|
return;
|
|
e = p + vlen;
|
|
while(res->nkouho < Maxkouho && p < e){
|
|
while(p < e && *p == ' ')
|
|
p++;
|
|
sp = p;
|
|
while(p < e && *p != ' ')
|
|
p++;
|
|
if(sinit(&tmp, sp, p - sp) && tmp.n > 0 &&
|
|
(req->lang == LangEMOJI || scmp(&tmp, &req->key) != 0))
|
|
res->kouho[res->nkouho++] = tmp;
|
|
}
|
|
}
|
|
|
|
void
|
|
dictthread(void*)
|
|
{
|
|
Dictreq req;
|
|
static Dictres res;
|
|
|
|
threadsetname("dict");
|
|
for(;;){
|
|
if(chanrecv(dictreqc, &req) < 0)
|
|
break;
|
|
while(channbrecv(dictreqc, &req) > 0)
|
|
;
|
|
dictlookup(&req, &res);
|
|
chansend(dictresc, &res);
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
}
|