123 lines
2.2 KiB
C
123 lines
2.2 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
void
|
|
dictlookup(Dictreq *req, Dictres *res)
|
|
{
|
|
Lang *l;
|
|
Hmap *dict;
|
|
Hnode *n;
|
|
char *p, *e, *sp;
|
|
Str tmp;
|
|
|
|
res->key = req->pre;
|
|
res->nkouho = 0;
|
|
res->lang = req->lang;
|
|
if(req->key.n == 0)
|
|
return;
|
|
l = getlang(req->lang);
|
|
dict = l ? l->dict : nil;
|
|
if(dict == nil)
|
|
return;
|
|
n = hmapget(dict, &req->key);
|
|
if(n == nil || n->vlen == 0)
|
|
return;
|
|
p = n->val;
|
|
e = p + n->vlen;
|
|
while(res->nkouho < Maxkouho && p < e){
|
|
while(p < e && *p == ' ')
|
|
p++;
|
|
if(p == e)
|
|
break;
|
|
sp = p;
|
|
while(p < e && *p != ' ')
|
|
p++;
|
|
sinit(&tmp, sp, p - sp);
|
|
if(req->lang == LangEMOJI || scmp(&tmp, &req->key) != 0)
|
|
res->kouho[res->nkouho++] = tmp;
|
|
if(p < e)
|
|
p++;
|
|
}
|
|
}
|
|
|
|
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 Hmap*
|
|
dictopen(char *path)
|
|
{
|
|
Hmap *h;
|
|
Biobuf *b;
|
|
Str key;
|
|
char *line, *tab, *p, *e;
|
|
int len, lineno;
|
|
|
|
b = Bopen(path, OREAD);
|
|
if(b == nil)
|
|
die("can't open: %s", path);
|
|
h = hmapalloc(4096);
|
|
lineno = 0;
|
|
while((line = Brdstr(b, '\n', 1)) != nil){
|
|
lineno++;
|
|
len = strlen(line);
|
|
if(len > 0 && line[len-1] == '\r')
|
|
line[--len] = '\0';
|
|
if(len == 0 || line[0] == ';'){
|
|
free(line);
|
|
continue;
|
|
}
|
|
tab = strchr(line, '\t');
|
|
if(tab == nil || tab == line || tab >= line + len - 1 ||
|
|
strchr(tab+1, '\t') != nil)
|
|
die("malformed dictionary: %s:%d", path, lineno);
|
|
*tab = '\0';
|
|
if(utflen(line) > Maxrunes)
|
|
die("dictionary key too long: %s:%d", path, lineno);
|
|
for(p = tab+1; p < line+len; p = e+1){
|
|
e = memchr(p, ' ', line+len-p);
|
|
if(e == nil)
|
|
e = line+len;
|
|
if(utfnlen(p, e-p) > Maxrunes)
|
|
die("dictionary candidate too long: %s:%d", path, lineno);
|
|
if(e == line+len)
|
|
break;
|
|
}
|
|
sinit(&key, line, tab - line);
|
|
hmapset(&h, &key, tab+1, len - (tab - line) - 1);
|
|
free(line);
|
|
}
|
|
Bterm(b);
|
|
return h;
|
|
}
|
|
|
|
void
|
|
dictinit(char *dir)
|
|
{
|
|
char *path;
|
|
int i;
|
|
|
|
for(i = 0; i < nlang; i++){
|
|
if(langs[i].dictname == nil)
|
|
continue;
|
|
path = smprint("%s/%s.dict", dir, langs[i].dictname);
|
|
if(path == nil)
|
|
die("out of memory");
|
|
langs[i].dict = dictopen(path);
|
|
free(path);
|
|
}
|
|
}
|