/* * 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 #include #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); }