#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. */ static int words(Lang *l, Str *key, 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 && (l->lang == LangEMOJI || scmp(&tmp, key) != 0)) out[n++] = tmp; } return n; } /* 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) { 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); 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. */ int dictlookup(Lang *l, Str *key, Str *out, int max) { int ni; ni = key->n == 0 ? -1 : trienode(l->dict, 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); } 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"); } }