update.
[chise/libchise.git] / chise.c
1 /* Copyright (C) 2003,2004,2005 MORIOKA Tomohiko
2    This file is part of the CHISE Library.
3
4    The CHISE Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The CHISE Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the CHISE Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <dirent.h>
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27 #include "sysdep.h"
28 #include "chise.h"
29
30 const unsigned char chise_db_format_version[] = CHISE_DB_FORMAT_VERSION;
31 const unsigned char chise_db_dir[] = CHISE_DB_DIR;
32 const unsigned char chise_system_db_dir[] = CHISE_SI_DB_DIR;
33
34
35 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
36
37
38 int
39 chise_value_size (const CHISE_Value* s)
40 {
41   return s->size;
42 }
43
44 unsigned char*
45 chise_value_data (const CHISE_Value* s)
46 {
47   return s->data;
48 }
49
50 unsigned char*
51 chise_value_to_c_string (const CHISE_Value* s)
52 {
53   return s->data;
54 }
55
56
57 CHISE_Char_ID
58 chise_char_id_parse_c_string (unsigned char *str, size_t len);
59
60 int
61 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len);
62
63
64 CHISE_DS*
65 CHISE_DS_open (CHISE_DS_Type type, const unsigned char* location,
66                int subtype, int modemask)
67 {
68   CONCORD_DS ds = concord_open_ds (type, location, subtype, modemask);
69
70   if (ds == NULL)
71     return NULL;
72
73   return concord_ds_get_genre (ds, "character");
74 }
75
76 int
77 CHISE_DS_close (CHISE_DS* ds)
78 {
79   return concord_close_ds (concord_genre_get_data_source (ds));
80 }
81
82 unsigned char*
83 chise_ds_location (CHISE_DS* ds)
84 {
85   return concord_ds_location (concord_genre_get_data_source (ds));
86 }
87
88 CHISE_Feature
89 chise_ds_get_feature (CHISE_DS* ds, const unsigned char* name)
90 {
91   return concord_genre_get_feature (ds, name);
92 }
93
94 CHISE_CCS
95 chise_ds_get_ccs (CHISE_DS* ds, const unsigned char* name)
96 {
97   return concord_genre_get_index (ds, name);
98 }
99
100 CHISE_Property
101 chise_ds_get_property (CHISE_DS* ds, const unsigned char* name)
102 {
103   CONCORD_Genre genre
104     = concord_ds_get_genre (concord_genre_get_data_source (ds),
105                             "feature");
106
107   if (genre == NULL)
108     return NULL;
109
110   return concord_genre_get_feature (genre, name);
111 }
112
113 int
114 chise_ds_foreach_char_feature_name (CHISE_DS* ds,
115                                     int (*func) (CHISE_DS* ds,
116                                                  unsigned char* name))
117 {
118   return concord_genre_foreach_feature_name (ds, func);
119 }
120
121 int
122 chise_feature_setup_db (CHISE_Feature feature, int writable)
123 {
124   return concord_feature_setup_db (feature, writable);
125 }
126
127 int
128 chise_feature_sync (CHISE_Feature feature)
129 {
130   return concord_feature_sync (feature);
131 }
132
133 int
134 chise_char_set_feature_value (CHISE_Char_ID cid,
135                               CHISE_Feature feature,
136                               unsigned char* value)
137 {
138   unsigned char key_buf[8];
139
140   chise_format_char_id (cid, key_buf, 8);
141   return concord_obj_put_feature_value_str (key_buf, feature, value);
142 }
143
144 int
145 chise_char_load_feature_value (CHISE_Char_ID cid,
146                                CHISE_Feature feature,
147                                CHISE_Value* valdatum)
148 {
149   unsigned char key_buf[8];
150
151   chise_format_char_id (cid, key_buf, 8);
152   return concord_obj_get_feature_value_string (key_buf, feature, valdatum);
153 }
154
155 unsigned char*
156 chise_char_gets_feature_value (CHISE_Char_ID cid,
157                                CHISE_Feature feature,
158                                unsigned char* dst, size_t size)
159 {
160   unsigned char key_buf[8];
161
162   chise_format_char_id (cid, key_buf, 8);
163   return concord_obj_gets_feature_value (key_buf, feature, dst, size);
164 }
165
166 static int
167 (*chise_feature_for_a_char_with_value_func) (CHISE_Char_ID cid,
168                                              CHISE_Feature feature,
169                                              CHISE_Value* valdatum);
170
171 int
172 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
173                                                CONCORD_Feature feature,
174                                                CONCORD_String value);
175 int
176 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
177                                                CONCORD_Feature feature,
178                                                CONCORD_String value)
179 {
180   unsigned char* cid_str = CONCORD_String_data (object_id);
181   int cid_len = strnlen (cid_str, CONCORD_String_size (object_id));
182   CHISE_Char_ID cid = chise_char_id_parse_c_string (cid_str, cid_len);
183
184   return chise_feature_for_a_char_with_value_func (cid, feature, value);
185 }
186
187 int
188 chise_feature_foreach_char_with_value (CHISE_Feature feature,
189                                        int (*func) (CHISE_Char_ID cid,
190                                                     CHISE_Feature feature,
191                                                     CHISE_Value* valdatum))
192 {
193   chise_feature_for_a_char_with_value_func = func;
194   return
195     concord_feature_foreach_obj_string
196     (feature, &chise_feature_foreach_char_with_value_wrapper);
197 }
198
199
200 int
201 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
202 {
203   return concord_index_setup_db (ccs, writable);
204 }
205
206 int
207 chise_ccs_sync (CHISE_CCS ccs)
208 {
209   return concord_index_sync (ccs);
210 }
211
212 CHISE_Char_ID
213 chise_ccs_decode (CHISE_CCS ccs, int code_point)
214 {
215   char key_buf[16];
216   CONCORD_String_Tank value;
217   int status;
218
219   sprintf(key_buf, "%d", code_point);
220   status = concord_index_strid_get_obj_string (ccs, key_buf, &value);
221   if (!status)
222     {
223       unsigned char *str
224         = (unsigned char *)CONCORD_String_data (&value);
225       int len = strnlen (str, CONCORD_String_size (&value));
226
227       return chise_char_id_parse_c_string (str, len);
228     }
229   return -1;
230 }
231
232 int
233 chise_ccs_set_decoded_char (CHISE_CCS ccs,
234                             int code_point, CHISE_Char_ID cid)
235 {
236   char key_buf[16], val_buf[8];
237
238   sprintf(key_buf, "%d", code_point);
239   chise_format_char_id (cid, val_buf, 8);
240   return concord_index_strid_put_obj (ccs, key_buf, val_buf);
241 }
242
243
244 int
245 chise_property_setup_db (CHISE_Property property, int writable)
246 {
247   return concord_feature_setup_db (property, writable);
248 }
249
250 int
251 chise_property_sync (CHISE_Property property)
252 {
253   return concord_feature_sync (property);
254 }
255
256 int
257 chise_feature_set_property_value (CHISE_Feature feature,
258                                   CHISE_Property property,
259                                   unsigned char* value)
260 {
261   return
262     concord_obj_put_feature_value_str
263     (concord_feature_get_name (feature), property, value);
264 }
265
266 int
267 chise_feature_load_property_value (CHISE_Feature feature,
268                                    CHISE_Property property,
269                                    CHISE_Value* valdatum)
270 {
271   return
272     concord_obj_get_feature_value_string
273     (concord_feature_get_name (feature), property, valdatum);
274 }
275
276 unsigned char*
277 chise_feature_gets_property_value (CHISE_Feature feature,
278                                    CHISE_Property property,
279                                    unsigned char* buf, size_t size)
280 {
281   return
282     concord_obj_gets_feature_value (concord_feature_get_name (feature),
283                                     property, buf, size);
284 }
285
286
287 CHISE_Char_ID
288 chise_char_id_parse_c_string (unsigned char *str, size_t len)
289 {
290   int i = 0;
291
292   if ( (len >= 2) && (str[i++] == '?') )
293     {
294       unsigned char c = str[i++];
295       int counter;
296       CHISE_Char_ID cid;
297
298       if (c == '\\')
299         {
300           if (len < 3)
301             return -1;
302           c = str[i++];
303           if (c == '^')
304             {
305               if (len < 4)
306                 return -1;
307               c = str[i++];
308               if (c == '?')
309                 return 0x7F;
310               else
311                 return c & (0x80 | 0x1F);
312             }
313         }
314       if ( c < 0xC0 )
315         {
316           cid = c;
317           counter = 0;
318         }
319       else if ( c < 0xE0 )
320         {
321           cid = c & 0x1f;
322           counter = 1;
323         }
324       else if ( c < 0xF0 )
325         {
326           cid = c & 0x0f;
327           counter = 2;
328         }
329       else if ( c < 0xF8 )
330         {
331           cid = c & 0x07;
332           counter = 3;
333         }
334       else if ( c < 0xFC )
335         {
336           cid = c & 0x03;
337           counter = 4;
338         }
339       else
340         {
341           cid = c & 0x01;
342           counter = 5;
343         }
344
345       if (counter + 2 <= len)
346         {
347           int j;
348
349           for (j = 0; j < counter; j++)
350             cid = (cid << 6) | (str[j + i] & 0x3F);
351           return cid;
352         }
353     }
354   return -1;
355 }
356
357 int
358 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
359 {
360   int i = 0;
361
362   dest[i++] = '?';
363   if (cid == '\t')
364     {
365       dest[i++] = '\\';
366       dest[i++] = 't';
367       dest[i] = '\0';
368       return i;
369     }
370   else if (cid == '\n')
371     {
372       dest[i++] = '\\';
373       dest[i++] = 'n';
374       dest[i] = '\0';
375       return i;
376     }
377   else if (cid == '\r')
378     {
379       dest[i++] = '\\';
380       dest[i++] = 'r';
381       dest[i] = '\0';
382       return i;
383     }
384   else if (cid == 0x1C)
385     {
386       dest[i++] = '\\';
387       dest[i++] = '^';
388       dest[i++] = '\\';
389       dest[i++] = '\\';
390       dest[i] = '\0';
391       return i;
392     }
393   else if (cid <= 0x1F)
394     {
395       dest[i++] = '\\';
396       dest[i++] = '^';
397       dest[i++] = '@' + cid;
398       dest[i] = '\0';
399       return i;
400     }
401   else if ( (cid == ' ') || (cid == '"') ||
402             (cid == '#') || (cid == '\'') ||
403             (cid == '(') || (cid == ')') ||
404             (cid == ',') || (cid == '.') ||
405             (cid == ';') || (cid == '?') ||
406             (cid == '[') || (cid == '\\') ||
407             (cid == ']') || (cid == '`') )
408     {
409       dest[i++] = '\\';
410       dest[i++] = cid;
411       dest[i] = '\0';
412       return i;
413     }
414   else if (cid <= 0x7E)
415     {
416       dest[i++] = cid;
417       dest[i] = '\0';
418       return i;
419     }
420   else if (cid == 0x7F)
421     {
422       dest[i++] = '\\';
423       dest[i++] = '^';
424       dest[i++] = '?';
425       dest[i] = '\0';
426       return i;
427     }
428   else if (cid <= 0x9F)
429     {
430       dest[i++] = '\\';
431       dest[i++] = '^';
432       dest[i++] = ((cid + '@') >> 6) | 0xC0;
433       dest[i++] = ((cid + '@') & 0x3F) | 0x80;
434       dest[i] = '\0';
435       return i;
436     }
437   else if (cid <= 0x7FF)
438     {
439       dest[i++] = (cid >> 6) | 0xC0;
440       dest[i++] = (cid & 0x3F) | 0x80;
441       dest[i] = '\0';
442       return i;
443     }
444   else if (cid <= 0xFFFF)
445     {
446       dest[i++] = (cid >> 12) | 0xE0;
447       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
448       dest[i++]=  (cid        & 0x3F) | 0x80;
449       dest[i] = '\0';
450       return i;
451     }
452   else if (cid <= 0x1FFFFF)
453     {
454       dest[i++]=  (cid >> 18) | 0xF0;
455       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
456       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
457       dest[i++]=  (cid        & 0x3F) | 0x80;
458       dest[i] = '\0';
459       return i;
460     }
461   else if (cid <= 0x3FFFFFF)
462     {
463       dest[i++]=  (cid >> 24) | 0xF8;
464       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
465       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
466       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
467       dest[i++]=  (cid        & 0x3F) | 0x80;
468       dest[i] = '\0';
469       return i;
470     }
471   else
472     {
473       dest[i++]=  (cid >> 30) | 0xFC;
474       dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
475       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
476       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
477       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
478       dest[i++]=  (cid        & 0x3F) | 0x80;
479       dest[i] = '\0';
480       return i;
481     }
482 }