2 * ³Ø½¬¤ÎÍúÎò¤Ê¤É¤ò´ÉÍý¤¹¤ë¤¿¤á¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹
3 * ʸ»úÎó(xstr)¤ò¥¡¼¤Ë¤·¤Æ¹â®¤Ë¹Ô(row)¤ò¸¡º÷¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡¥
4 * Ê£¿ô¤Î¥»¥¯¥·¥ç¥ó¤ò¤â¤Ä¤³¤È¤¬¤Ç¤¡¤³Ø½¬¤Î°ã¤¦¥Õ¥§¡¼¥º¤Ê¤É¤ËÂбþ¤¹¤ë
5 * (¥»¥¯¥·¥ç¥ó * ʸ»úÎó -> ¹Ô)
6 * ³Æ¹Ô¤Ïʸ»úÎ󤫿ô¤ò»ý¤ÄÇÛÎó¤Ë¤Ê¤Ã¤Æ¤¤¤ë
8 * ¡Ö¥Ñ¥È¥ê¥·¥¢¡¦¥È¥é¥¤¡×¤È¤¤¤¦¥Ç¡¼¥¿¹½Â¤¤ò»ÈÍѤ·¤Æ¤¤¤ë¡£
9 * ¼«Á³¸À¸ì¤Î¸¡º÷¤Ê¤É¤ò°·¤Ã¤Æ¤¤¤ë¶µ²Ê½ñ¤ò»²¾È¤Î¤³¤È
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 2 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Funded by IPA̤Ƨ¥½¥Õ¥È¥¦¥§¥¢ÁϤ»ö¶È 2002 1/18
28 * Funded by IPA̤Ƨ¥½¥Õ¥È¥¦¥§¥¢ÁϤ»ö¶È 2005
29 * Copyright (C) 2005 YOSHIDA Yuichi
30 * Copyright (C) 2000-2006 TABATA Yusuke
31 * Copyright (C) 2000-2003 UGAWA Tomoharu
32 * Copyright (C) 2001-2002 TAKAI Kosuke
35 * ¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£""¤Ïƿ̾¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£¤Ç¤¢¤ê¡¤
36 * ¥Õ¥¡¥¤¥ë¤Ø¤ÎÆɤ߽ñ¤¤Ï¹Ô¤ï¤Ê¤¤¡¥
38 #include <sys/types.h>
47 #include <anthy/anthy.h>
48 #include <anthy/dic.h>
49 #include <anthy/alloc.h>
50 #include <anthy/conf.h>
51 #include <anthy/ruleparser.h>
52 #include <anthy/record.h>
53 #include <anthy/logger.h>
54 #include <anthy/prediction.h>
57 #include "dic_personality.h"
59 /* ¸Ä¿Í¼½ñ¤ò¥»¡¼¥Ö¤¹¤ë¥Õ¥¡¥¤¥ë̾¤Îsuffix */
60 #define ENCODING_SUFFIX ".utf8"
64 RT_EMPTY, RT_VAL, RT_XSTR, RT_XSTRP
81 struct record_val *vals;
89 struct record_row row;
90 struct trie_node *lru_prev, *lru_next; /* ξü¥ë¡¼¥× */
91 int dirty; /* LRU ¤Î¤¿¤á¤Î used, sused ¥Ó¥Ã¥È */
96 struct trie_node root;
100 #define LRU_USED 0x01
101 #define LRU_SUSED 0x02
102 #define PROTECT 0x04 /* º¹Ê¬½ñ¤½Ð¤·»þ¤Ë»È¤¦(LRU¤È¤Ï´Ø·¸¤Ê¤¤)
103 * º¹Ê¬½ñ¤½Ð¤·¤Ç¤Ï¡¢¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤¹Á°¤Ë
104 * ¥Õ¥¡¥¤¥ë¾å¤Ë¾¤Î¥×¥í¥»¥¹¤¬µÏ¿¤·¤¿¹¹¿·¤ò
105 * Æɤ߹þ¤à¡£¤½¤ì¤Ë¤è¤Ã¤Æ¡¢¤³¤ì¤«¤éÄɲä·¤è
106 * ¤¦¤È¤¹¤ë¥Î¡¼¥É¤¬¾Ã¤µ¤ì¤ë¤Î¤òËɤ°
110 * USED: ¥á¥â¥ê¾å¤Ç»È¤ï¤ì¤¿
111 * SUSED: Êݸ¤µ¤ì¤¿ used ¥Ó¥Ã¥È
113 * LRU¥ê¥¹¥È¾å¤Ç¤Ï¡¢ USED ¤Ïɬ¤º¥ê¥¹¥ÈÀèƬ¤Ëʤó¤Ç¤¤¤ë¤¬¡¢ SUSED ¤Ï
114 * ¥Õ¥é¥°¤Ê¤·¤Î¥Î¡¼¥É¤Èº®ºß¤·¤Æ¤¤¤ë²ÄǽÀ¤¬¤¢¤ë¡£
116 * n¸Ä¤ò»Ä¤¹¤è¤¦¤Ë»ØÄꤵ¤ì¤¿»þ¤ÎÆ°ºî
118 * LRU ¥ê¥¹¥È¤ÎÀèƬ¤«¤é n ÈÖÌܰʹߤò¾Ã¤¹
119 * 2. used + sused > n
121 * sused -> sused ¥Õ¥é¥°¤òÍ
125 * ¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤¹»þ¤Ë¡¢ used || sused -> sused ¤È¤·¤Æ½ñ¤½Ð¤¹
129 struct record_section {
131 struct trie_root cols;
132 struct record_section *next;
133 int lru_nr_used, lru_nr_sused; /* LRU ÍÑ */
138 struct record_section section_list; /* section¤Î¥ê¥¹¥È*/
139 struct record_section *cur_section;
140 struct trie_root xstrs; /* xstr ¤ò intern ¤¹¤ë¤¿¤á¤Î trie */
141 struct trie_node *cur_row;
142 int row_dirty; /* cur_row ¤¬Êݸ¤ÎɬÍפ¬¤¢¤ë¤« */
146 const char *id; /* ¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£¤Îid */
147 char *base_fn; /* ´ðËÜ¥Õ¥¡¥¤¥ë ÀäÂХѥ¹ */
148 char *journal_fn; /* º¹Ê¬¥Õ¥¡¥¤¥ë ÀäÂХѥ¹ */
150 time_t base_timestamp; /* ´ðËÜ¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥× */
151 int last_update; /* º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤ËÆɤó¤À°ÌÃÖ */
152 time_t journal_timestamp; /* º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥× */
155 /* º¹Ê¬¤¬100KB±Û¤¨¤¿¤é´ðËÜ¥Õ¥¡¥¤¥ë¤Ø¥Þ¡¼¥¸ */
156 #define FILE2_LIMIT 102400
161 * ¸Ä¿Í¤´¤È( record_stat ¤´¤È)¤Ëʸ»úÎó¤ò intern ¤¹¤ë¡£¤³¤ì¤Ï¡¢
162 * ¥á¥â¥ê¤ÎÀáÌó¤Î¾¤Ë¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush »þ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
163 * ͳÍ褹¤ë xstr ¤¬Ìµ¸ú¤Ë¤Ê¤ë¤Î¤òËɤ°ÌÜŪ¤¬¤¢¤ë¡£
164 * ¤·¤¿¤¬¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush »þ¤Ç¤â xstr ¤Î intern ÍÑ
165 * ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹ xstrs ¤Ï¤½¤Î¤Þ¤ÞÊݸ¤¹¤ë¡£
167 * xstrs: xstr ¤Î intern ÍѤΥǡ¼¥¿¥Ù¡¼¥¹
168 * row ¤Î key ¤ò intern ¤µ¤ì¤¿ xstr ¤È¤·¤Æ»È¤¦¡£
169 * row ¤Ë value ¤Ï»ý¤¿¤Ê¤¤¡£
170 * (¾ÍèŪ¤Ë¤Ï»²¾È¥«¥¦¥ó¥¿¤ò¤Ä¤±¤Æ¤â¤¤¤¤¤«¤â)
171 * »²¾È: intern_xstr()
176 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÎÊݸ¡¢Ê£¿ô¤Î anthy ¥é¥¤¥Ö¥é¥ê¤ò¥ê¥ó¥¯¤·¤¿
177 * ¥×¥í¥»¥¹¤Î³Ø½¬ÍúÎò¤ÎƱ´ü¤Î¤¿¤á¤Ë¡¢³Ø½¬ÍúÎò¤Î¹¹¿·¾ðÊó¤ò
178 * Ãà°ì¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤¹¡£
180 * ¡¦´ðËÜ¥Õ¥¡¥¤¥ë ¸Å¤¤ anthy ¤Î³Ø½¬ÍúÎò¤ÈƱ¤¸·Á¼°¡£
181 * º¹Ê¬¾ðÊó¤òŬÍѤ¹¤ë¸µ¤È¤Ê¤ë¥Õ¥¡¥¤¥ë¡£
182 * ´ðËÜŪ¤Ë¤Ïµ¯Æ°»þ¤À¤±¤ËÆɤ߹þ¤à¡£
183 * ¤³¤Î¥×¥í¥°¥é¥àÃæ¤Ç¥Õ¥¡¥¤¥ë1¡¤base¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
184 * ¡¦º¹Ê¬¥Õ¥¡¥¤¥ë ´ðËÜ¥Õ¥¡¥¤¥ë¤ËÂФ¹¤ë¹¹¿·¾ðÊó¡£
185 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ¹¤ë¹¹¿·¤¬¥³¥ß¥Ã¥È¤µ¤ì¤ë¤¿¤Ó¤Ë
187 * ¤³¤Î¥×¥í¥°¥é¥àÃæ¤Ç¥Õ¥¡¥¤¥ë2¡¤journal¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
189 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ¹¤ë¹¹¿·¤¬¥³¥ß¥Ã¥È¤µ¤ì¤ë¤È¡¢¤Þ¤ºº¹Ê¬¥Õ¥¡¥¤¥ë
190 * ¤Ë¾¤Î¥×¥í¥»¥¹¤¬Äɲä·¤¿¹¹¿·¾ðÊó¤òÆɤ߹þ¤ß¡¢¤½¤Î¸å¤Ë¼«Ê¬¤Î
191 * ¥³¥ß¥Ã¥È¤·¤¿¹¹¿·¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤¹¡£
192 * ¤³¤ì¤é¤Ï¥í¥Ã¥¯¥Õ¥¡¥¤¥ë¤òÍѤ¤¤Æ¥¢¥È¥ß¥Ã¥¯¤Ë¹Ô¤ï¤ì¤ë¡£¤Þ¤¿¡¢
193 * ´ðËÜ¥Õ¥¡¥¤¥ë¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤È¤â¡¢¥í¥Ã¥¯¤ò¼è¤Ã¤Æ¤¤¤ë´Ö¤·¤«
194 * ¥ª¡¼¥×¥ó¤·¤Æ¤¤¤Æ¤Ï¤¤¤±¤Ê¤¤¡£
196 * ÄɲäϤ¹¤Ç¤Ë¥á¥â¥ê¾å¤Ç¹¹¿·¤µ¤ì¤¿ row ¤ò¥³¥ß¥Ã¥È¤Ë¤è¤Ã¤Æ
197 * ¥á¥â¥ê¤Ë½ñ¤½Ð¤¹¤¿¤á¡¢
198 * 1. ¥³¥ß¥Ã¥ÈÂÐ¾Ý row °Ê³°¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Î¾ðÊó¤Ç
199 * 2. ¥³¥ß¥Ã¥ÈÂÐ¾Ý row ¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤·
200 * ¤È¤¹¤ë¡£ºï½ü¤Ï¤Þ¤À¥á¥â¥ê¾å¤Ë row ¤¬»Ä¤Ã¤Æ¤¤¤ë¾õÂ֤ǥ³¥ß¥Ã¥È
201 * ¤¬¹Ô¤ï¤ì¤ë(ºï½üÍ×µá¤ò¥³¥ß¥Ã¥È¤È¤·¤Æ°·¤¦)¤¿¤á¡¢
202 * 1. ºï½ü¤Î¾ðÊó¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤·
203 * 2. º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¤Ë¤è¤êºï½üÍ×µá¤â¼Â¹Ô¤¹¤ë
205 * ´ðËÜ¥Õ¥¡¥¤¥ë¤Î¹¹¿·:
206 * º¹Ê¬¥Õ¥¡¥¤¥ë¤¬¤¢¤ëÄøÅÙÈîÂç²½¤¹¤ë¤È¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¾ðÊó¤ò
207 * ´ðËÜ¥Õ¥¡¥¤¥ë¤ËÈ¿±Ç¤·¤Æº¹Ê¬¥Õ¥¡¥¤¥ë¤ò¶õ¤Ë¤¹¤ë¡£
209 * º¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤·¤ò¹Ô¤Ã¤¿¸å¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÂ礤µ¤òÄ´¤Ù¡¢
210 * ÈîÂç²½¤·¤Æ¤¤¤ì¤Ð¡¢¤½¤Î¤È¤¤Î¥á¥â¥ê¾å¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹(¤³¤ì¤Ë¤Ï
211 * Á´¤Æ¤Îº¹Ê¬¥Õ¥¡¥¤¥ë¤Î¹¹¿·¤¬Å¬ÍѤµ¤ì¤Æ¤¤¤ë)¤ò´ðËÜ¥Õ¥¡¥¤¥ë¤Ë
213 * ¤½¤ì°Ê³°¤Î¥×¥í¥»¥¹:
214 * º¹Ê¬¥Õ¥¡¥¤¥ë¤òÆɤàÁ°¤Ë¡¢´ðËÜ¥Õ¥¡¥¤¥ë¤¬¹¹¿·¤µ¤ì¤Æ¤¤¤ë¤«¤ò
215 * ¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥×¤ÇÄ´¤Ù¡¢¹¹¿·¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¥ß¥Ã¥È
216 * ¤µ¤ì¤¿¹¹¿·¾ðÊó¤òľ¤Á¤Ë¹¹¿·¥Õ¥¡¥¤¥ë¤ËÄɲä·¡¢¥á¥â¥ê¾å¤Î
217 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò flush ¤·¤¿¸å´ðËÜ¥Õ¥¡¥¤¥ë¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤ò
219 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush ¤Ë¤è¤ê¡¢
220 * ¡¦cur_row ¤¬Ìµ¸ú¤Ë¤Ê¤ë (NULL ¤Ë¤Ê¤ë)
221 * ¡¦cur_section ¤Î͸úÀ¤ÏÊݸ¤µ¤ì¤ë(section¤Ï²òÊü¤·¤Ê¤¤)
222 * ¡¦xstr ¤Ï intern ¤·¤Æ¤¤¤ì¤ÐÊݸ¤µ¤ì¤ë
223 * (¤¹¤Ù¤Æ¤Î xstr ¤Ï intern ¤µ¤ì¤Æ¤¤¤ë¤Ï¤º)
224 * ·ë¶É¡¢¼¡¤ÎÍͤˤʤë:
225 * if (´ðËÜ¥Õ¥¡¥¤¥ë¤¬¹¹¿·¤µ¤ì¤Æ¤¤¤ë) {
226 * º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¥³¥ß¥Ã¥È¤µ¤ì¤¿¹¹¿·¤ò½ñ¤½Ð¤¹;
227 * ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Õ¥é¥Ã¥·¥å;
228 * ´ðËÜ¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¥¯¥ê¥¢;
229 * º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
232 * º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
233 * º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤½Ð¤·;
235 * º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤½Ð¤·;
236 * º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
239 * if (º¹Ê¬¥Õ¥¡¥¤¥ë¤¬Â礤¤) {
240 * ´ðËÜ¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤½Ð¤·;
241 * º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¥¯¥ê¥¢;
245 static allocator record_ator;
248 static void init_trie_root(struct trie_root *n);
249 static int trie_key_nth_bit(xstr* key, int n);
250 static int trie_key_first_diff_bit_1byte(xchar c1, xchar c2);
251 static int trie_key_first_diff_bit(xstr *k1, xstr *k2);
252 static int trie_key_cmp(xstr *k1, xstr *k2);
253 static void trie_key_dup(xstr *dst, xstr *src);
254 static void trie_row_init(struct record_row *rc);
255 static void trie_row_free(struct record_row *rc);
256 static struct trie_node *trie_find(struct trie_root *root, xstr *key);
257 static struct trie_node *trie_insert(struct trie_root *root, xstr *key,
258 int dirty, int *nr_used, int *nr_sused);
259 static void trie_remove(struct trie_root *root, xstr *key,
260 int *nr_used, int *nr_sused);
261 static struct trie_node *trie_first(struct trie_root *root);
262 static struct trie_node *trie_next(struct trie_root *root,
263 struct trie_node *cur);
264 static void trie_remove_all(struct trie_root *root,
265 int *nr_used, int *nr_sused);
266 static void trie_remove_old(struct trie_root *root, int count,
267 int* nr_used, int* nr_sused);
268 static void trie_mark_used(struct trie_root *root, struct trie_node *n,
269 int *nr_used, int *nr_sused);
274 * struct trie_node¤Î¤¦¤Árow°Ê³°¤ÎÉôʬ¤Èrow.key¤ò»ÈÍÑ
275 * ºï½ü¤Î»þ¤Ïtrie_row_free¤ò»È¤Ã¤Ærow¤ÎÆâÍƤò²òÊü
278 #define PUTNODE(x) ((x) == &root->root ? printf("root\n") : anthy_putxstrln(&(x)->row.key))
280 debug_trie_dump(FILE* fp, struct trie_node* n, int encoding)
285 if (n->l->bit > n->bit) {
286 cnt = debug_trie_dump(fp, n->l, encoding);
288 if (n->l->row.key.len == -1) {
290 fprintf(fp, "root\n");
294 anthy_sputxstr(buf, &n->l->row.key, encoding);
295 fprintf(fp, "%s\n", buf);
301 if (n->r->bit > n->bit) {
302 return cnt + debug_trie_dump(fp, n->r, encoding);
304 if (n->r->row.key.len == -1) {
306 fprintf(fp, "root\n");
310 anthy_sputxstr(buf, &n->r->row.key, encoding);
311 fprintf(fp, "%s\n", buf);
321 init_trie_root(struct trie_root *root)
324 root->node_ator = anthy_create_allocator(sizeof(struct trie_node), NULL);
332 trie_row_init(&n->row);
338 * bit1: head¤Î¥¡¼¤À¤±0
339 * bit2: ʸ»úÎó¤Î¥Ó¥Ã¥È0
340 * bit3: ʸ»úÎó¤Î¥Ó¥Ã¥È1
342 * ʸ»úÎóŤò±Û¤¨¤ë¤È0
345 trie_key_nth_bit(xstr* key, int n)
351 return key->len + 1; /* key->len == -1 ? 0 : non-zero */
356 pos = n / (sizeof(xchar) << 3);
357 if (pos >= key->len) {
360 return key->str[pos] & (1 << (n % (sizeof(xchar) << 3)));
365 /* c1 == c2 ¤Ç¤Ï¸Æ¤ó¤Ç¤Ï¤¤¤±¤Ê¤¤ */
367 trie_key_first_diff_bit_1byte(xchar c1, xchar c2)
371 for (i = 0, ptn = c1 ^ c2; !(ptn & 1); i++, ptn >>= 1 )
377 * k1 == k2 ¤Ç¤Ï¸Æ¤ó¤Ç¤Ï¤¤¤±¤Ê¤¤
378 * ki->str[0 .. (ki->len - 1)]¤Ë0¤Ï¤Ê¤¤¤È²¾Äê
380 #define MIN(a,b) ((a)<(b)?(a):(b))
382 trie_key_first_diff_bit(xstr *k1, xstr *k2)
387 len = MIN(k1->len, k2->len);
391 for ( i = 0 ; i < len ; i++ ){
392 if (k1->str[i] != k2->str[i]) {
393 return (2 + (i * (sizeof(xchar) << 3)) +
394 trie_key_first_diff_bit_1byte(k1->str[i], k2->str[i]));
397 if (k1->len < k2->len) {
398 return (2 + (i * (sizeof(xchar) << 3)) +
399 trie_key_first_diff_bit_1byte(0, k2->str[i]));
401 return (2 + (i * (sizeof(xchar) << 3)) +
402 trie_key_first_diff_bit_1byte(k1->str[i], 0));
408 trie_key_cmp(xstr *k1, xstr *k2)
410 if (k1->len == -1 || k2->len == -1) {
411 return k1->len - k2->len;
413 return anthy_xstrcmp(k1, k2);
417 trie_key_dup(xstr *dst, xstr *src)
419 dst->str = anthy_xstr_dup_str(src);
426 static struct trie_node *
427 trie_find(struct trie_root *root, xstr *key)
434 while (p->bit < q->bit) {
436 q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
438 return trie_key_cmp(&q->row.key,key) ? NULL : q;
442 * ºÇĹ¥Þ¥Ã¥Á¤Î¤¿¤á¤ÎÊä½õ´Ø¿ô
443 * key ¤Çõº÷¤·¤Æ¡¢»Ï¤á¤Æ°ìÃפ·¤Ê¤¯¤Ê¤Ã¤¿¥Î¡¼¥É¤òÊÖ¤¹¡£
445 static struct trie_node *
446 trie_find_longest (struct trie_root* root, xstr *key)
453 while (p->bit < q->bit) {
455 q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
462 * Äɲä·¤¿¥Î¡¼¥É¤òÊÖ¤¹
463 * ¤¹¤Ç¤ËƱ¤¸¥¡¼¤ò¤â¤Ä¥Î¡¼¥É¤¬¤¢¤ë¤È¤¤Ï¡¢Äɲ令º¤Ë0¤òÊÖ¤¹
465 static struct trie_node *
466 trie_insert(struct trie_root *root, xstr *key,
467 int dirty, int *nr_used, int *nr_sused)
476 while (p->bit < q->bit) {
478 q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
480 if (trie_key_cmp(&q->row.key,key) == 0) {
481 /* USED > SUSED > 0 ¤Ç¶¯¤¤Êý¤ò»Ä¤¹ */
482 if (dirty == LRU_USED) {
483 trie_mark_used(root, q, nr_used, nr_sused);
484 } else if (q->dirty == 0) {
489 i = trie_key_first_diff_bit(&q->row.key, key);
492 while (p->bit < q->bit && i > q->bit) {
494 q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
496 n = anthy_smalloc(root->node_ator);
497 trie_row_init(&n->row);
498 trie_key_dup(&n->row.key, key);
500 if (trie_key_nth_bit(key, i)) {
514 if (dirty == LRU_USED) {
515 root->root.lru_next->lru_prev = n;
516 n->lru_prev = &root->root;
517 n->lru_next = root->root.lru_next;
518 root->root.lru_next = n;
521 root->root.lru_prev->lru_next = n;
522 n->lru_next = &root->root;
523 n->lru_prev = root->root.lru_prev;
524 root->root.lru_prev = n;
525 if (dirty == LRU_SUSED) {
534 * ¥Î¡¼¥É¤ò¸«¤Ä¤±¤ë¤Èºï½ü¤¹¤ë
535 * ÆâÉô¤Çtrie_row_free¤ò¸Æ¤Ó¡¢¥¡¼¤ò´Þ¤à¥Ç¡¼¥¿Éôʬ¤òfree¤¹¤ë
537 * ¥Ç¡¼¥¿¤È¥Î¡¼¥É¤òºï½ü¤¹¤ë¡£
538 * ºï½üÂоݤΥǡ¼¥¿¤Ïºï½üÂоݤΥΡ¼¥É¤Ë³ÊǼ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï
539 * ¸Â¤é¤Ê¤¤¤³¤È¤ËÃí°Õ¡£
540 * 1. ºï½üÂоݤÎÍÕ¤ò»ý¤Ä¥Î¡¼¥É¤Ëºï½üÂоݤÎÍÕ¤¬´Þ¤Þ¤ì¤Æ¤¤¤ë¤È¤
541 * ºï½üÂоݤΥΡ¼¥É¤Ï¡¢»Ò¤Ø¤Î»Þ¤Î¤¦¤Á¡¢À¸¤¤Î¤³¤ë»Þ¤ò¿Æ¤ËÅϤ·¤Æ»à¤Ì
542 * 2. ºï½üÂоݤÎÍÕ¤ò»ý¤Ä¥Î¡¼¥É¤ÎÁÄÀè¤Ëºï½üÂоݤÎÍÕ¤¬´Þ¤Þ¤ì¤Æ¤¤¤ë¤È¤
543 * 1. ¤Ë²Ã¤¨¤Æ¡¢ºï½üÂоݤÎÍÕ¤ò¤â¤Ä¥Î¡¼¥É¤ò»¦¤·¤Æ¡¢Âå¤ï¤ê¤Ëºï½ü
544 * ÂоݤΥΡ¼¥É¤òºï½üÂоݤÎÍÕ¤ò¤â¤Ä¥Î¡¼¥É¤Î°ÌÃ֤˰ÜÆ°¤µ¤»À¸¤«¤¹
547 trie_remove(struct trie_root *root, xstr *key,
548 int *nr_used, int *nr_sused)
552 struct trie_node **pp = NULL; /* gcc ¤Î warning ²óÈò */
553 struct trie_node **qq;
557 while (p->bit < q->bit) {
560 qq = trie_key_nth_bit(key,p->bit) ? &p->r : &p->l;
563 if (trie_key_cmp(&q->row.key, key) != 0) {
574 s = trie_key_nth_bit(key, r->bit) ? r->r : r->l;
576 *pp = (p->r == q) ? p->l : p->r;
580 if (trie_key_nth_bit(key, r->bit)) {
587 *pp = (p->r == q) ? p->l : p->r;
589 p->lru_prev->lru_next = p->lru_next;
590 p->lru_next->lru_prev = p->lru_prev;
591 if (p->dirty == LRU_USED) {
593 } else if (p->dirty == LRU_SUSED) {
596 trie_row_free(&p->row);
597 anthy_sfree(root->node_ator, p);
600 /* head°Ê³°¤Î¥Î¡¼¥É¤¬¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤¹ */
601 static struct trie_node *
602 trie_first (struct trie_root *root)
604 return root->root.lru_next == &root->root ?
605 NULL : root->root.lru_next;
608 /* ¼¡¤Î¥Î¡¼¥É¤¬¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤¹ */
609 static struct trie_node *
610 trie_next (struct trie_root *root,
611 struct trie_node *cur)
613 return cur->lru_next == &root->root ? 0 : cur->lru_next;
617 * head°Ê³°Á´¤Æ¤Î¥Î¡¼¥É¤òºï½ü¤¹¤ë
618 * ÆâÉô¤Çtrie_row_free¤ò¸Æ¤Ó¡¢¥¡¼¤ò´Þ¤à¥Ç¡¼¥¿Éôʬ¤òfree¤¹¤ë
621 trie_remove_all (struct trie_root *root,
622 int *nr_used, int *nr_sused)
625 for (p = root->root.lru_next; p != &root->root; p = p->lru_next) {
626 trie_row_free(&p->row);
628 anthy_free_allocator(root->node_ator);
629 init_trie_root(root);
635 * LRU ¥ê¥¹¥È¤ÎÀèƬ¤«¤é count ÈÖÌܤޤǤò»Ä¤·¤Æ»Ä¤ê¤ò²òÊü¤¹¤ë
638 trie_remove_old (struct trie_root *root, int count,
639 int *nr_used, int *nr_sused)
644 if (*nr_used > count) {
645 for (p = root->root.lru_next; count; count--, p = p->lru_next)
647 /* p ¤«¤é head ¤Þ¤Ç¤ò¾Ã¤¹ */
648 for ( ; p != &root->root; p = q) {
650 trie_remove(root, &p->row.key, nr_used, nr_sused);
652 } else if (*nr_used + *nr_sused > count) {
653 for (p = root->root.lru_next; p->dirty == LRU_USED; p = p->lru_next)
656 * p ¤«¤é root ¤Þ¤Ç sused -> dirty := 0
659 for ( ; p != &root->root; p = q) {
661 if (p->dirty == LRU_SUSED) {
664 trie_remove(root, &p->row.key, nr_used, nr_sused);
672 trie_mark_used (struct trie_root *root, struct trie_node *n,
673 int *nr_used, int *nr_sused)
686 n->lru_prev->lru_next = n->lru_next;
687 n->lru_next->lru_prev = n->lru_prev;
688 root->root.lru_next->lru_prev = n;
689 n->lru_next = root->root.lru_next;
690 root->root.lru_next = n;
691 n->lru_prev = &root->root;
695 * ¥È¥é¥¤¤Î¼ÂÁõ¤Ï¤³¤³¤Þ¤Ç
699 do_get_index_xstr(struct record_stat *rec)
704 return &rec->cur_row->row.key;
707 static struct record_section*
708 do_select_section(struct record_stat *rst, const char *name, int flag)
710 struct record_section *rsc;
712 for (rsc = rst->section_list.next; rsc; rsc = rsc->next) {
713 if (!strcmp(name, rsc->name)) {
719 rsc = malloc(sizeof(struct record_section));
720 rsc->name = strdup(name);
721 rsc->next = rst->section_list.next;
722 rst->section_list.next = rsc;
723 rsc->lru_nr_used = 0;
724 rsc->lru_nr_sused = 0;
725 init_trie_root(&rsc->cols);
732 static struct trie_node*
733 do_select_longest_row(struct record_section *rsc, xstr *name)
735 struct trie_node *mark, *found;
739 if ((NULL == name) || (NULL == name->str) || (name->len < 1) || (0 == name->str[0])) {
740 /* ¼½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
744 mark = trie_find_longest(&rsc->cols, name);
746 for (i = (mark->row.key.len <= name->len) ? mark->row.key.len : name->len; i > 1; i--) { /* ÉÔÀµ¤Ê¥á¥â¥ê¥¢¥¯¥»¥¹¤Î½¤Àµ */
747 /* ¥ë¡¼¥È¥Î¡¼¥É¤Ï i == 1 ¤Ç¥Þ¥Ã¥Á¤¹¤ë¤Î¤Ç½ü³°
748 * trie_key_nth_bit »²¾È
751 found = trie_find(&rsc->cols, &xs);
759 static struct trie_node*
760 do_select_row(struct record_section* rsc, xstr *name,
763 struct trie_node *node;
766 node = trie_insert(&rsc->cols, name, dirty,
767 &rsc->lru_nr_used, &rsc->lru_nr_sused);
769 node->row.nr_vals = 0;
772 node = trie_find(&rsc->cols, name);
775 node = trie_find(&rsc->cols, name);
781 do_mark_row_used(struct record_section* rsc, struct trie_node* node)
783 trie_mark_used(&rsc->cols, node, &rsc->lru_nr_used, &rsc->lru_nr_sused);
787 do_truncate_section(struct record_stat *s, int count)
789 if (!s->cur_section) {
793 trie_remove_old(&s->cur_section->cols, count,
794 &s->cur_section->lru_nr_used,
795 &s->cur_section->lru_nr_sused);
799 static struct trie_node*
800 do_select_first_row(struct record_section *rsc)
802 return trie_first(&rsc->cols);
805 static struct trie_node*
806 do_select_next_row(struct record_section *rsc,
807 struct trie_node* node)
809 return trie_next(&rsc->cols, node);
814 do_get_nr_values(struct trie_node *node)
818 return node->row.nr_vals;
821 static struct record_val *
822 get_nth_val_ent(struct trie_node *node, int n, int f)
824 struct record_row *col;
829 if (n < do_get_nr_values(node)) {
830 return &col->vals[n];
834 col->vals = realloc(col->vals, sizeof(struct record_val)*(n + 1));
835 for (i = col->nr_vals; i < n+1; i++) {
836 col->vals[i].type = RT_EMPTY;
838 col->nr_vals = n + 1;
839 return &col->vals[n];
845 free_val_contents(struct record_val* v)
849 anthy_free_xstr_str(&v->u.str);
860 do_set_nth_value(struct trie_node *node, int nth, int val)
862 struct record_val *v = get_nth_val_ent(node, nth, 1);
866 free_val_contents(v);
872 do_get_nth_value(struct trie_node *node, int n)
874 struct record_val *v = get_nth_val_ent(node, n, 0);
875 if (v && v->type == RT_VAL) {
882 intern_xstr (struct trie_root* xstrs, xstr* xs)
884 struct trie_node* node;
887 if ((NULL == xs) || (NULL == xs->str) || (xs->len < 1) || (0 == xs->str[0])) {
888 /* ¼½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
891 node = trie_find(xstrs, xs);
893 node = trie_insert(xstrs, xs, 0, &dummy, &dummy);
894 return &node->row.key;
898 do_set_nth_xstr (struct trie_node *node, int nth, xstr *xs,
899 struct trie_root* xstrs)
901 struct record_val *v = get_nth_val_ent(node, nth, 1);
905 free_val_contents(v);
907 v->u.strp = intern_xstr(xstrs, xs);
911 do_truncate_row (struct trie_node* node, int n)
914 if (n < node->row.nr_vals) {
915 for (i = n; i < node->row.nr_vals; i++) {
916 free_val_contents(node->row.vals + i);
918 node->row.vals = realloc(node->row.vals,
919 sizeof(struct record_val)* n);
920 node->row.nr_vals = n;
925 do_remove_row (struct record_section* rsc,
926 struct trie_node* node)
929 xs = anthy_xstr_dup(&node->row.key);
930 trie_remove(&rsc->cols, &node->row.key,
931 &rsc->lru_nr_used, &rsc->lru_nr_sused);
937 do_get_nth_xstr(struct trie_node *node, int n)
939 struct record_val *v = get_nth_val_ent(node, n, 0);
941 if (v->type == RT_XSTR) {
943 } else if (v->type == RT_XSTRP) {
951 lock_record (struct record_stat* rs)
956 anthy_priv_dic_lock();
960 unlock_record (struct record_stat* rs)
965 anthy_priv_dic_unlock();
968 /* ºÆÆɤ߹þ¤ß¤ÎɬÍפ¬¤¢¤ë¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë
969 * ɬÍפ¬¤¢¤ì¤ÐÊÖ¤êÃͤ¬1¤Ë¤Ê¤ë */
971 check_base_record_uptodate(struct record_stat *rst)
977 anthy_check_user_dir();
978 if (stat(rst->base_fn, &st) < 0) {
980 } else if (st.st_mtime != rst->base_timestamp) {
989 * ROW := OPERATION SECTION KEY VALUE*
990 * OPERATION := "ADD" (Äɲäޤ¿¤ÏLRU¹¹¿·)
992 * SECTION := (ʸ»úÎó)
995 * TD := TYPE DATA (¶õÇò¤ò¤¢¤±¤º¤Ë½ñ¤¯)
998 * DATA := (·¿¤´¤È¤Ë¥·¥ê¥¢¥é¥¤¥º¤·¤¿¤â¤Î)
1002 read_1_token (FILE* fp, int* eol)
1015 case EOF: case '\n':
1019 if (c == EOF || c == '\n') {
1024 in_quote = !in_quote;
1026 case ' ': case '\t': case '\r':
1038 s = (char*) realloc(s, len + 2);
1050 /* journal¤«¤éADD¤Î¹Ô¤òÆɤà */
1052 read_add_row(FILE *fp, struct record_stat* rst,
1053 struct record_section* rsc)
1059 struct trie_node* node;
1061 token = read_1_token(fp, &eol);
1066 xs = anthy_cstr_to_xstr(/* xstr ·¿¤òɽ¤¹ S ¤òÆɤ߼ΤƤë */
1069 node = do_select_row(rsc, xs, 1, LRU_USED);
1070 anthy_free_xstr(xs);
1073 if (node->dirty & PROTECT) {
1074 /* Êݸ¤¹¤Ù¤ row ¤Ê¤Î¤Ç¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤òÆɤ߼ΤƤë */
1076 free(read_1_token(fp, &eol));
1083 token = read_1_token(fp, &eol);
1090 xs = anthy_cstr_to_xstr(token + 1, rst->encoding);
1091 do_set_nth_xstr(node, n, xs, &rst->xstrs);
1092 anthy_free_xstr(xs);
1097 do_set_nth_value(node, n, atoi(token + 1));
1104 do_truncate_row(node, n);
1107 /* journal¤«¤éDEL¤Î¹Ô¤òÆɤà */
1109 read_del_row(FILE *fp, struct record_stat* rst,
1110 struct record_section* rsc)
1112 struct trie_node* node;
1117 token = read_1_token(fp, &eol);
1122 xs = anthy_cstr_to_xstr(/* xstr ·¿¤òɽ¤¹ S ¤òÆɤßÈô¤Ð¤¹ */
1125 if ((node = do_select_row(rsc, xs, 0, 0)) != NULL) {
1126 do_remove_row(rsc, node);
1128 anthy_free_xstr(xs);
1132 /** º¹Ê¬¥Õ¥¡¥¤¥ë¤«¤é1¹ÔÆɤ߹þ¤à */
1134 read_1_row(struct record_stat* rst, FILE* fp, char *op)
1137 struct record_section* rsc;
1140 sec_name = read_1_token(fp, &eol);
1141 if (!sec_name || eol) {
1145 rsc = do_select_section(rst, sec_name, 1);
1151 if (strcmp(op, "ADD") == 0) {
1152 read_add_row(fp, rst, rsc);
1153 } else if (strcmp(op, "DEL") == 0) {
1154 read_del_row(fp, rst, rsc);
1159 * journal(º¹Ê¬)¥Õ¥¡¥¤¥ë¤òÆɤà
1162 read_journal_record(struct record_stat* rs)
1170 fp = fopen(rs->journal_fn, "r");
1174 if (fstat(fileno(fp), &st) == -1) {
1178 if (st.st_size < rs->last_update) {
1179 /* ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤¬¾®¤µ¤¯¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢
1180 * ºÇ½é¤«¤éÆɤ߹þ¤à */
1181 fseek(fp, 0, SEEK_SET);
1183 fseek(fp, rs->last_update, SEEK_SET);
1185 rs->journal_timestamp = st.st_mtime;
1189 op = read_1_token(fp, &eol);
1191 read_1_row(rs, fp, op);
1195 rs->last_update = ftell(fp);
1200 write_string(FILE* fp, const char* str)
1202 fprintf(fp, "%s", str);
1205 /* ¥À¥Ö¥ë¥¯¥ª¡¼¥È¤â¤·¤¯¤Ï¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å¤Ë¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å¤òÉÕ¤±¤ë */
1207 write_quote_string(FILE* fp, const char* str)
1211 for (p = str; *p; p++) {
1212 if (*p == '\"' || *p == '\\') {
1220 write_quote_xstr(FILE* fp, xstr* xs, int encoding)
1224 if ((NULL == xs) || (NULL == xs->str) || (xs->len < 1) || (0 == xs->str[0])) {
1225 /* ¼½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
1229 buf = (char*) alloca(xs->len * 6 + 2); /* EUC ¤Þ¤¿¤ÏUTF8¤ò²¾Äê */
1230 anthy_sputxstr(buf, xs, encoding);
1231 write_quote_string(fp, buf);
1235 write_number(FILE* fp, int x)
1237 fprintf(fp, "%d", x);
1240 /* journal¤Ë1¹ÔÄɵ¤¹¤ë */
1242 commit_add_row(struct record_stat* rst,
1243 const char* sname, struct trie_node* node)
1248 fp = fopen(rst->journal_fn, "a");
1253 write_string(fp, "ADD \"");
1254 write_quote_string(fp, sname);
1255 write_string(fp, "\" S\"");
1256 write_quote_xstr(fp, &node->row.key, rst->encoding);
1257 write_string(fp, "\"");
1259 for (i = 0; i < node->row.nr_vals; i++) {
1260 switch (node->row.vals[i].type) {
1262 write_string(fp, " E");
1265 write_string(fp, " N");
1266 write_number(fp, node->row.vals[i].u.val);
1269 write_string(fp, " S\"");
1270 write_quote_xstr(fp, &node->row.vals[i].u.str, rst->encoding);
1271 write_string(fp, "\"");
1274 write_string(fp, " S\"");
1275 write_quote_xstr(fp, node->row.vals[i].u.strp, rst->encoding);
1276 write_string(fp, "\"");
1280 write_string(fp, "\n");
1281 rst->last_update = ftell(fp);
1285 /* Á´¤Æ¤Î row ¤ò²òÊü¤¹¤ë */
1287 clear_record(struct record_stat* rst)
1289 struct record_section *rsc;
1290 for (rsc = rst->section_list.next; rsc; rsc = rsc->next) {
1291 trie_remove_all(&rsc->cols, &rsc->lru_nr_used, &rsc->lru_nr_sused);
1293 rst->cur_row = NULL;
1296 /* ´ðËÜ¥Õ¥¡¥¤¥ë¤òÆɤà */
1298 read_session(struct record_stat *rst)
1303 while (!anthy_read_line(&tokens, &nr)) {
1307 struct trie_node* node;
1309 if (!strcmp(tokens[0], "---") && nr > 1) {
1310 /* ¥»¥¯¥·¥ç¥ó¤ÎÀÚ¤ìÌÜ */
1312 rst->cur_section = do_select_section(rst, tokens[1], 1);
1315 if (!in_section || nr < 2) {
1316 /* ¥»¥¯¥·¥ç¥ó¤¬»Ï¤Þ¤Ã¤Æ¤Ê¤¤ or ¹Ô¤¬ÉÔ´°Á´ */
1319 /* ¹ÔƬ¤ÎLRU¤Î¥Þ¡¼¥¯¤òÆɤà */
1320 if (tokens[0][0] == '-') {
1322 } else if (tokens[0][0] == '+') {
1326 xs = anthy_cstr_to_xstr(&tokens[0][1], rst->encoding);
1327 node = do_select_row(rst->cur_section, xs, 1, dirty);
1328 anthy_free_xstr(xs);
1332 rst->cur_row = node;
1334 for (i = 1; i < nr; i++) {
1335 if (tokens[i][0] == '"') {
1337 str = strdup(&tokens[i][1]);
1338 str[strlen(str) - 1] = 0;
1339 xs = anthy_cstr_to_xstr(str, rst->encoding);
1341 do_set_nth_xstr(rst->cur_row, i-1, xs, &rst->xstrs);
1342 anthy_free_xstr(xs);
1343 }else if (tokens[i][0] == '*') {
1345 get_nth_val_ent(rst->cur_row, i-1, 1);
1347 do_set_nth_value(rst->cur_row, i-1, atoi(tokens[i]));
1355 /* ¤¤¤Þ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò²òÊü¤·¤¿¸å¤Ë¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤à */
1357 read_base_record(struct record_stat *rst)
1364 anthy_check_user_dir();
1366 if (anthy_open_file(rst->base_fn) == -1) {
1373 if (stat(rst->base_fn, &st) == 0) {
1374 rst->base_timestamp = st.st_mtime;
1376 rst->last_update = 0;
1380 open_tmp_in_recorddir(void)
1385 sid = anthy_conf_get_str("SESSION-ID");
1386 hd = anthy_conf_get_str("HOME");
1387 pn = alloca(strlen(hd)+strlen(sid) + 10);
1388 sprintf(pn, "%s/.anthy/%s", hd, sid);
1389 return fopen(pn, "w");
1393 * °ì»þ¥Õ¥¡¥¤¥ë¤«¤ébase¥Õ¥¡¥¤¥ë¤Ørename¤¹¤ë
1396 update_file(const char *fn)
1401 hd = anthy_conf_get_str("HOME");
1402 sid = anthy_conf_get_str("SESSION-ID");
1403 tmp_fn = alloca(strlen(hd)+strlen(sid) + 10);
1405 sprintf(tmp_fn, "%s/.anthy/%s", hd, sid);
1406 if (rename(tmp_fn, fn)){
1407 anthy_log(0, "Failed to update record file %s -> %s.\n", tmp_fn, fn);
1411 /* ¥«¥é¥à¤òÊݸ¤¹¤ë */
1413 save_a_row(FILE *fp, struct record_stat* rst,
1414 struct record_row *c, int dirty)
1417 char *buf = alloca(c->key.len * 6 + 2);
1418 /* LRU¤Î¥Þ¡¼¥¯¤ò½ÐÎÏ */
1424 anthy_sputxstr(buf, &c->key, rst->encoding);
1426 fprintf(fp, "%s ", buf);
1428 for (i = 0; i < c->nr_vals; i++) {
1429 struct record_val *val = &c->vals[i];
1430 switch (val->type) {
1435 /* should not happen */
1437 write_quote_xstr(fp, &val->u.str, rst->encoding);
1443 write_quote_xstr(fp, val->u.strp, rst->encoding);
1447 fprintf(fp, "%d ", val->u.val);
1450 anthy_log(0, "Faild to save an unkonwn record. (in record.c)\n");
1458 update_base_record(struct record_stat* rst)
1460 struct record_section *sec;
1461 struct trie_node *col;
1465 /* °ì»þ¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Ærecord¤ò½ñ¤½Ð¤¹ */
1466 anthy_check_user_dir();
1467 fp = open_tmp_in_recorddir();
1469 anthy_log(0, "Failed to open temporaly session file.\n");
1472 /* ³Æ¥»¥¯¥·¥ç¥ó¤ËÂФ·¤Æ */
1473 for (sec = rst->section_list.next;
1474 sec; sec = sec->next) {
1475 if (!trie_first(&sec->cols)) {
1476 /*¤³¤Î¥»¥¯¥·¥ç¥ó¤Ï¶õ*/
1479 /* ¥»¥¯¥·¥ç¥ó¶³¦¤Îʸ»úÎó */
1480 fprintf(fp, "--- %s\n", sec->name);
1481 /* ³Æ¥«¥é¥à¤òÊݸ¤¹¤ë */
1482 for (col = trie_first(&sec->cols); col;
1483 col = trie_next(&sec->cols, col)) {
1484 save_a_row(fp, rst, &col->row, col->dirty);
1489 /* ËÜÍè¤Î̾Á°¤Ërename¤¹¤ë */
1490 update_file(rst->base_fn);
1492 if (stat(rst->base_fn, &st) == 0) {
1493 rst->base_timestamp = st.st_mtime;
1495 /* journal¥Õ¥¡¥¤¥ë¤ò¾Ã¤¹ */
1496 unlink(rst->journal_fn);
1497 rst->last_update = 0;
1501 commit_del_row(struct record_stat* rst,
1502 const char* sname, struct trie_node* node)
1506 fp = fopen(rst->journal_fn, "a");
1510 write_string(fp, "DEL \"");
1511 write_quote_string(fp, sname);
1512 write_string(fp, "\" S\"");
1513 write_quote_xstr(fp, &node->row.key, rst->encoding);
1514 write_string(fp, "\"");
1515 write_string(fp, "\n");
1520 * sync_add: ADD ¤Î½ñ¤¹þ¤ß
1521 * sync_del_and_del: DEL ¤Î½ñ¤¹þ¤ß¤Èºï½ü
1522 * ¤É¤Á¤é¤â½ñ¤¹þ¤ß¤ÎÁ°¤Ë¡¢Â¾¤Î¥×¥í¥»¥¹¤Ë¤è¤Ã¤Æ¥Ç¥£¥¹¥¯¾å¤ËÊݸ¤µ¤ì¤¿
1523 * ¹¹¿·¤ò¥á¥â¥ê¾å¤ËÆɤ߹þ¤à¡£
1524 * ¤³¤Î¤È¤¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥Õ¥é¥Ã¥·¥å¤¹¤ë²ÄǽÀ¤â¤¢¤ë¡£¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î
1525 * ¥Õ¥é¥Ã¥·¥å¤¬¤¢¤ë¤È¡¢ cur_row ¤ÈÁ´¤Æ¤Î xstr ¤Ï̵¸ú¤Ë¤Ê¤ë¡£
1526 * ¤¿¤À¤·¡¢ cur_section ¤Î͸úÀ¤ÏÊݸ¤µ¤ì¤ë¡£
1529 sync_add(struct record_stat* rst, struct record_section* rsc,
1530 struct trie_node* node)
1533 if (check_base_record_uptodate(rst)) {
1534 node->dirty |= PROTECT;
1535 /* º¹Ê¬¥Õ¥¡¥¤¥ë¤À¤±Æɤà */
1536 read_journal_record(rst);
1537 node->dirty &= ~PROTECT;
1538 commit_add_row(rst, rsc->name, node);
1541 commit_add_row(rst, rsc->name, node);
1542 read_base_record(rst);
1543 read_journal_record(rst);
1545 if (rst->last_update > FILE2_LIMIT) {
1546 update_base_record(rst);
1552 sync_del_and_del(struct record_stat* rst, struct record_section* rsc,
1553 struct trie_node* node)
1556 commit_del_row(rst, rsc->name, node);
1557 if (!check_base_record_uptodate(rst)) {
1558 read_base_record(rst);
1560 read_journal_record(rst);
1561 if (rst->last_update > FILE2_LIMIT) {
1562 update_base_record(rst);
1573 read_prediction_node(struct trie_node *n, struct prediction_t* predictions, int index)
1576 int nr_predictions = do_get_nr_values(n);
1577 for (i = 0; i < nr_predictions; i += 2) {
1578 time_t t = do_get_nth_value(n, i);
1579 xstr* xs = do_get_nth_xstr(n, i + 1);
1582 predictions[index].timestamp = t;
1583 predictions[index].src_str = anthy_xstr_dup(&n->row.key);
1584 predictions[index].str = anthy_xstr_dup(xs);
1594 * trieÃæ¤ò¤¿¤É¤ê¡¢prefix¤¬¥Þ¥Ã¥Á¤·¤¿¤éread_prediction_node¤ò
1595 * ¸Æ¤ó¤Çpredictions¤ÎÇÛÎó¤Ë·ë²Ì¤òÄɲ乤롣
1598 traverse_record_for_prediction(xstr* key, struct trie_node *n,
1599 struct prediction_t* predictions, int index)
1601 if (n->l->bit > n->bit) {
1602 index = traverse_record_for_prediction(key, n->l, predictions, index);
1604 if (n->l->row.key.len != -1) {
1605 if (anthy_xstrncmp(&n->l->row.key, key, key->len) == 0) {
1606 index = read_prediction_node(n->l, predictions, index);
1610 if (n->r->bit > n->bit) {
1611 index = traverse_record_for_prediction(key, n->r, predictions, index);
1613 if (n->r->row.key.len != -1) {
1614 if (anthy_xstrncmp(&n->r->row.key, key, key->len) == 0) {
1615 index = read_prediction_node(n->r, predictions, index);
1624 * key ¤Îʸ»úÎóŤò±Û¤¨¤ë¤«¡¢¥Î¡¼¥É¤¬Ìµ¤¯¤Ê¤Ã¤¿¤éõº÷ÂǤÁÀÚ¤ê
1625 * trie¤Îkey¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤ë¤È¤³¤í¤Ç¤Ê¤Ê¤¯¤ÆÍÕ¤òÊÖ¤¹
1627 static struct trie_node *
1628 trie_find_for_prediction (struct trie_root* root, xstr *key)
1630 struct trie_node *p;
1631 struct trie_node *q;
1636 while (p->bit < q->bit) {
1638 if ((q->bit - 2) / (int)(sizeof(xchar) << 3) >= key->len) {
1643 q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
1649 prediction_cmp(const void* lhs, const void* rhs)
1651 struct prediction_t *lpre = (struct prediction_t*)lhs;
1652 struct prediction_t *rpre = (struct prediction_t*)rhs;
1653 return rpre->timestamp - lpre->timestamp;
1657 anthy_traverse_record_for_prediction(xstr* key, struct prediction_t* predictions)
1659 struct trie_node* mark;
1661 if (anthy_select_section("PREDICTION", 0)) {
1665 /* »ØÄꤵ¤ì¤¿Ê¸»úÎó¤òprefix¤Ë»ý¤Änode¤òõ¤¹ */
1666 mark = trie_find_for_prediction(&anthy_current_record->cur_section->cols, key);
1670 nr_predictions = traverse_record_for_prediction(key, mark, predictions, 0);
1672 /* ¥¿¥¤¥à¥¹¥¿¥ó¥×¤Çͽ¬¸õÊä¤ò¥½¡¼¥È¤¹¤ë */
1673 qsort(predictions, nr_predictions, sizeof(struct prediction_t), prediction_cmp);
1675 return nr_predictions;
1678 /* Wrappers begin.. */
1680 anthy_select_section(const char *name, int flag)
1682 struct record_stat* rst;
1683 struct record_section* rsc;
1685 rst = anthy_current_record;
1686 if (rst->row_dirty && rst->cur_section && rst->cur_row) {
1687 sync_add(rst, rst->cur_section, rst->cur_row);
1689 rst->cur_row = NULL;
1691 rsc = do_select_section(rst, name, flag);
1695 rst->cur_section = rsc;
1700 anthy_select_row(xstr *name, int flag)
1702 struct record_stat* rst;
1703 struct trie_node* node;
1705 rst = anthy_current_record;
1706 if (!rst->cur_section) {
1709 if (rst->row_dirty && rst->cur_row) {
1710 sync_add(rst, rst->cur_section, rst->cur_row);
1713 node = do_select_row(rst->cur_section, name, flag, LRU_USED);
1717 rst->cur_row = node;
1718 rst->row_dirty = flag;
1723 anthy_select_longest_row(xstr *name)
1725 struct record_stat* rst;
1726 struct trie_node* node;
1728 rst = anthy_current_record;
1729 if (!rst->cur_section)
1732 if (rst->row_dirty && rst->cur_row) {
1733 sync_add(rst, rst->cur_section, rst->cur_row);
1736 node = do_select_longest_row(rst->cur_section, name);
1741 rst->cur_row = node;
1747 anthy_truncate_section(int count)
1749 do_truncate_section(anthy_current_record, count);
1753 anthy_truncate_row(int nth)
1755 struct trie_node *cur_row = anthy_current_record->cur_row;
1759 do_truncate_row(cur_row, nth);
1764 anthy_mark_row_used(void)
1766 struct record_stat* rst = anthy_current_record;
1767 if (!rst->cur_row) {
1771 do_mark_row_used(rst->cur_section, rst->cur_row);
1772 sync_add(rst, rst->cur_section, rst->cur_row);
1778 anthy_set_nth_value(int nth, int val)
1780 struct record_stat* rst;
1782 rst = anthy_current_record;
1783 if (!rst->cur_row) {
1786 do_set_nth_value(rst->cur_row, nth, val);
1791 anthy_set_nth_xstr(int nth, xstr *xs)
1793 struct record_stat* rst = anthy_current_record;
1794 if (!rst->cur_row) {
1797 do_set_nth_xstr(rst->cur_row, nth, xs, &rst->xstrs);
1802 anthy_get_nr_values(void)
1804 return do_get_nr_values(anthy_current_record->cur_row);
1808 anthy_get_nth_value(int n)
1810 return do_get_nth_value(anthy_current_record->cur_row, n);
1814 anthy_get_nth_xstr(int n)
1816 return do_get_nth_xstr(anthy_current_record->cur_row, n);
1820 anthy_select_first_row(void)
1822 struct record_stat* rst;
1823 struct trie_node* node;
1825 rst = anthy_current_record;
1826 if (!rst->cur_section)
1829 if (rst->row_dirty && rst->cur_row) {
1830 sync_add(rst, rst->cur_section, rst->cur_row);
1833 node = do_select_first_row(rst->cur_section);
1837 rst->cur_row = node;
1843 anthy_select_next_row(void)
1845 struct record_stat* rst;
1846 struct trie_node* node;
1848 rst = anthy_current_record;
1849 if (!rst->cur_section || !rst->cur_row)
1852 /* sync_add() ¤Ç cur_row ¤¬Ìµ¸ú¤Ë¤Ê¤ë¤³¤È¤¬¤¢¤ë¤Î¤Ç¡¢
1853 * ¤¿¤È¤¨ row_dirty ¤Ç¤â sync_add() ¤·¤Ê¤¤
1856 node = do_select_next_row(rst->cur_section, rst->cur_row);
1859 rst->cur_row = node;
1865 anthy_get_index_xstr(void)
1867 return do_get_index_xstr(anthy_current_record);
1872 * trie_row_init ¤Ï²¿²ó¤è¤ó¤Ç¤â¤¤¤¤
1875 trie_row_init(struct record_row* rc)
1882 trie_row_free(struct record_row *rc)
1885 for (i = 0; i < rc->nr_vals; i++)
1886 free_val_contents(rc->vals + i);
1891 /* ¤¢¤ë¥»¥¯¥·¥ç¥ó¤Î¥Ç¡¼¥¿¤òÁ´¤Æ²òÊü¤¹¤ë */
1893 free_section(struct record_stat *r, struct record_section *rs)
1895 struct record_section *s;
1896 trie_remove_all(&rs->cols, &rs->lru_nr_used, &rs->lru_nr_sused);
1897 if (r->cur_section == rs) {
1901 for (s = &r->section_list; s && s->next; s = s->next) {
1902 if (s->next == rs) {
1903 s->next = s->next->next;
1907 free((void *)rs->name);
1912 /* ¤¹¤Ù¤Æ¤Î¥Ç¡¼¥¿¤ò²òÊü¤¹¤ë */
1914 free_record(struct record_stat *rst)
1916 struct record_section *rsc;
1917 for (rsc = rst->section_list.next; rsc; ){
1918 struct record_section *tmp;
1921 free_section(rst, tmp);
1923 rst->section_list.next = NULL;
1927 anthy_release_section(void)
1929 struct record_stat* rst;
1931 rst = anthy_current_record;
1932 if (!rst->cur_section) {
1935 free_section(rst, rst->cur_section);
1936 rst->cur_section = 0;
1940 anthy_release_row(void)
1942 struct record_stat* rst;
1944 rst = anthy_current_record;
1945 if (!rst->cur_section || !rst->cur_row) {
1950 /* sync_del_and_del ¤Çºï½ü¤â¤¹¤ë */
1951 sync_del_and_del(rst, rst->cur_section, rst->cur_row);
1952 rst->cur_row = NULL;
1956 check_record_encoding(struct record_stat *rst)
1959 if (anthy_open_file(rst->base_fn) == 0) {
1960 /* EUC¤ÎÍúÎò¥Õ¥¡¥¤¥ë¤¬¤¢¤Ã¤¿ */
1964 fp = fopen(rst->journal_fn, "r");
1966 /* EUC¤Îº¹Ê¬¥Õ¥¡¥¤¥ë¤¬¤¢¤Ã¤¿ */
1970 rst->encoding = ANTHY_UTF8_ENCODING;
1971 strcat(rst->base_fn, ENCODING_SUFFIX);
1972 strcat(rst->journal_fn, ENCODING_SUFFIX);
1976 record_dtor(void *p)
1979 struct record_stat *rst = (struct record_stat*) p;
1983 free(rst->journal_fn);
1985 trie_remove_all(&rst->xstrs, &dummy, &dummy);
1989 anthy_reload_record(void)
1992 struct record_stat *rst = anthy_current_record;
1994 if (stat(rst->journal_fn, &st) == 0 &&
1995 rst->journal_timestamp == st.st_mtime) {
2000 read_base_record(rst);
2001 read_journal_record(rst);
2006 anthy_init_record(void)
2008 record_ator = anthy_create_allocator(sizeof(struct record_stat),
2013 setup_filenames(const char *id, struct record_stat *rst)
2015 const char *home = anthy_conf_get_str("HOME");
2016 int base_len = strlen(home) + strlen(id) + 10;
2019 rst->base_fn = (char*) malloc(base_len +
2020 strlen("/.anthy/last-record1_"));
2021 sprintf(rst->base_fn, "%s/.anthy/last-record1_%s",
2024 rst->journal_fn = (char*) malloc(base_len +
2025 strlen("/.anthy/last-record2_"));
2026 sprintf(rst->journal_fn, "%s/.anthy/last-record2_%s",
2030 struct record_stat *
2031 anthy_create_record(const char *id)
2033 struct record_stat *rst;
2039 rst = anthy_smalloc(record_ator);
2041 rst->section_list.next = 0;
2042 init_trie_root(&rst->xstrs);
2043 rst->cur_section = 0;
2048 /* ¥Õ¥¡¥¤¥ë̾¤Îʸ»úÎó¤òºî¤ë */
2049 setup_filenames(id, rst);
2051 rst->last_update = 0;
2053 if (!strcmp(id, ANON_ID)) {
2057 anthy_check_user_dir();
2060 /* ¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤à */
2062 check_record_encoding(rst);
2063 read_base_record(rst);
2064 read_journal_record(rst);
2071 anthy_release_record(struct record_stat *rs)
2073 anthy_sfree(record_ator, rs);