diff options
Diffstat (limited to 'src-worddic/mem_dic.c')
-rw-r--r-- | src-worddic/mem_dic.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/src-worddic/mem_dic.c b/src-worddic/mem_dic.c new file mode 100644 index 0000000..9a26b71 --- /dev/null +++ b/src-worddic/mem_dic.c @@ -0,0 +1,250 @@ +/* + * mem_dic 辞書のキャッシュを行う + * + * キャッシュは読みの文字列と逆変換用かのフラグ(is_reverse)の + * 二つをキーとして操作される。 + * + * Copyright (C) 2000-2007 TABATA Yusuke + */ +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdlib.h> + +#include <anthy/alloc.h> +#include "dic_main.h" +#include "mem_dic.h" + +static allocator mem_dic_ator; + +static void +dic_ent_dtor(void *p) +{ + struct dic_ent *de = p; + if (de->str.str) { + free(de->str.str); + } +} + +static void +seq_ent_dtor(void *p) +{ + struct seq_ent *seq = p; + int i; + /**/ + for (i = 0; i < seq->nr_dic_ents; i++) { + anthy_sfree(seq->md->dic_ent_allocator, seq->dic_ents[i]); + } + if (seq->nr_dic_ents) { + free(seq->dic_ents); + } + /**/ + free(seq->str.str); +} + +static void +mem_dic_dtor(void *p) +{ + struct mem_dic * md = p; + anthy_free_allocator(md->seq_ent_allocator); + anthy_free_allocator(md->dic_ent_allocator); +} + +/** xstrに対応するseq_entを確保する */ +static struct seq_ent * +alloc_seq_ent_by_xstr(struct mem_dic * md, xstr *x, int is_reverse) +{ + struct seq_ent *se; + se = (struct seq_ent *)anthy_smalloc(md->seq_ent_allocator); + if (is_reverse) { + se->seq_type = ST_REVERSE; + } else { + se->seq_type = ST_NONE; + } + se->md = md; + se->str.len = x->len; + /**/ + se->nr_dic_ents = 0; + se->dic_ents = NULL; + /**/ + se->nr_compound_ents = 0; + + se->str.str = anthy_xstr_dup_str(x); + return se; +} + +/* ハッシュ関数。とりあえずてきとー */ +static int +hash_function(xstr *xs) +{ + if (xs->len) { + return xs->str[0]% HASH_SIZE; + } + return 0; +} + +/** xstrに対応するseq_entを返す */ +struct seq_ent * +anthy_mem_dic_alloc_seq_ent_by_xstr(struct mem_dic * md, xstr *xs, + int is_reverse) +{ + struct seq_ent *se; + int h; + /* キャッシュにあればそれを返す */ + se = anthy_mem_dic_find_seq_ent_by_xstr(md, xs, is_reverse); + if (se) { + return se; + } + /* キャッシュには無いので作る */ + se = alloc_seq_ent_by_xstr(md, xs, is_reverse); + + /* mem_dic中につなぐ */ + h = hash_function(xs); + se->next = md->seq_ent_hash[h]; + md->seq_ent_hash[h] = se; + + return se; +} + +static int +compare_seq_ent(struct seq_ent *seq, xstr *xs, int is_reverse) +{ + /* まず、どちらかが逆変換用のエントリかをチェック */ + if (seq->seq_type & ST_REVERSE) { + if (!is_reverse) { + return 1; + } + } else { + if (is_reverse) { + return 1; + } + } + /* 次に文字列の比較 */ + return anthy_xstrcmp(&seq->str, xs); +} + +/*** mem_dicの中から文字列に対応するseq_ent*を取得する + * */ +struct seq_ent * +anthy_mem_dic_find_seq_ent_by_xstr(struct mem_dic * md, xstr *xs, + int is_reverse) +{ + struct seq_ent *sn; + int h; + h = hash_function(xs); + for (sn = md->seq_ent_hash[h]; sn; sn = sn->next) { + if (!compare_seq_ent(sn, xs, is_reverse)){ + return sn; + } + } + return 0; +} + +void +anthy_mem_dic_release_seq_ent(struct mem_dic * md, xstr *xs, int is_reverse) +{ + struct seq_ent *sn; + struct seq_ent **sn_prev_p; + int h; + + h = hash_function(xs); + sn_prev_p = &md->seq_ent_hash[h]; + for (sn = md->seq_ent_hash[h]; sn; sn = sn->next) { + if (!compare_seq_ent(sn, xs, is_reverse)){ + *sn_prev_p = sn->next; + anthy_sfree(md->seq_ent_allocator, sn); + return; + } else { + sn_prev_p = &sn->next; + } + } +} + +/** seq_entにdic_entを追加する */ +void +anthy_mem_dic_push_back_dic_ent(struct seq_ent *se, int is_compound, + xstr *xs, wtype_t wt, + const char *wt_name, int freq, int feature) +{ + struct dic_ent *de; + de = anthy_smalloc(se->md->dic_ent_allocator); + de->type = wt; + de->wt_name = wt_name; + de->freq = freq; + de->feature = feature; + de->order = 0; + de->is_compound = is_compound; + de->str.len = xs->len; + de->str.str = anthy_xstr_dup_str(xs); + + if (is_compound) { + se->nr_compound_ents ++; + } + + /* orderを計算する */ + if (se->nr_dic_ents > 0) { + struct dic_ent *prev_de = se->dic_ents[se->nr_dic_ents-1]; + if (anthy_wtype_equal(prev_de->type, de->type) && + prev_de->freq > de->freq) { + de->order = prev_de->order + 1; + } + } + + /* 配列に追加する */ + se->nr_dic_ents ++; + se->dic_ents = realloc(se->dic_ents, + sizeof(struct dic_ent *)*se->nr_dic_ents); + se->dic_ents[se->nr_dic_ents-1] = de; +} + +struct mem_dic * +anthy_create_mem_dic(void) +{ + int i; + struct mem_dic *md; + + md = anthy_smalloc(mem_dic_ator); + for (i = 0; i < HASH_SIZE; i++) { + md->seq_ent_hash[i] = NULL; + } + + md->seq_ent_allocator = + anthy_create_allocator(sizeof(struct seq_ent), + seq_ent_dtor); + md->dic_ent_allocator = + anthy_create_allocator(sizeof(struct dic_ent), + dic_ent_dtor); + + return md; +} + +void +anthy_release_mem_dic(struct mem_dic * d) +{ + anthy_sfree(mem_dic_ator, d); +} + +void +anthy_init_mem_dic(void) +{ + mem_dic_ator = anthy_create_allocator(sizeof(struct mem_dic), + mem_dic_dtor); +} + +void +anthy_quit_mem_dic(void) +{ + anthy_free_allocator(mem_dic_ator); +} |