update.
[chise/libchise.git] / chise.c
1 /* Copyright (C) 2003,2004,2005,2011 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 #if 0
69   CONCORD_DS ds = concord_open_ds (type, location, subtype, modemask);
70 #else
71   CONCORD_DS ds = concord_open_env (location);
72 #endif
73
74   if (ds == NULL)
75     return NULL;
76
77   return concord_ds_get_genre (ds, "character");
78 }
79
80 int
81 CHISE_DS_close (CHISE_DS* ds)
82 {
83   return concord_close_ds (concord_genre_get_data_source (ds));
84 }
85
86 unsigned char*
87 chise_ds_location (CHISE_DS* ds)
88 {
89   return concord_ds_location (concord_genre_get_data_source (ds));
90 }
91
92 CHISE_Feature
93 chise_ds_get_feature (CHISE_DS* ds, const unsigned char* name)
94 {
95   return concord_genre_get_feature (ds, name);
96 }
97
98 CHISE_CCS
99 chise_ds_get_ccs (CHISE_DS* ds, const unsigned char* name)
100 {
101   return concord_genre_get_index (ds, name);
102 }
103
104 CHISE_Property
105 chise_ds_get_property (CHISE_DS* ds, const unsigned char* name)
106 {
107   CONCORD_Genre genre
108     = concord_ds_get_genre (concord_genre_get_data_source (ds),
109                             "feature");
110
111   if (genre == NULL)
112     return NULL;
113
114   return concord_genre_get_feature (genre, name);
115 }
116
117 int
118 chise_ds_foreach_char_feature_name (CHISE_DS* ds,
119                                     int (*func) (CHISE_DS* ds,
120                                                  unsigned char* name))
121 {
122   return concord_genre_foreach_feature_name (ds, func);
123 }
124
125 int
126 chise_feature_setup_db (CHISE_Feature feature, int writable)
127 {
128   return concord_feature_setup_db (feature, writable);
129 }
130
131 int
132 chise_feature_sync (CHISE_Feature feature)
133 {
134   return concord_feature_sync (feature);
135 }
136
137 int
138 chise_char_set_feature_value (CHISE_Char_ID cid,
139                               CHISE_Feature feature,
140                               unsigned char* value)
141 {
142   unsigned char key_buf[8];
143
144   chise_format_char_id (cid, key_buf, 8);
145   return concord_obj_put_feature_value_str (key_buf, feature, value);
146 }
147
148 int
149 chise_char_load_feature_value (CHISE_Char_ID cid,
150                                CHISE_Feature feature,
151                                CHISE_Value* valdatum)
152 {
153   unsigned char key_buf[8];
154
155   chise_format_char_id (cid, key_buf, 8);
156   return concord_obj_get_feature_value_string (key_buf, feature, valdatum);
157 }
158
159 int
160 chise_char_load_decomposition (CHISE_Char_ID cid,
161                                CHISE_Feature feature,
162                                CHISE_Char_ID* base_char, CHISE_Char_ID* comb_char)
163 {
164   unsigned char key_buf[8];
165   CHISE_Value value;
166   int status;
167   unsigned char* vp;
168   unsigned char* vp_ret;
169   int len;
170
171   chise_format_char_id (cid, key_buf, 8);
172   if ( status = concord_obj_get_feature_value_string (key_buf, feature, &value) )
173     return status;
174   len = chise_value_size (&value);
175   if ( len < (1 + 2 + 1 + 2 + 1) )
176     return -1;
177
178   vp = chise_value_data (&value);
179   if ( *vp++ != '(' )
180     return -1;
181   len--;
182
183   if ( ( vp_ret = memchr (vp, ' ', len) ) == NULL )
184     return -1;
185   *base_char = chise_char_id_parse_c_string (vp, vp_ret - vp + 1);
186   if ( *base_char == -1 )
187     return -1;
188   vp = vp_ret + 1;
189   len -= vp - chise_value_data (&value);
190   if ( len <= 1 )
191     return -1;
192
193   *comb_char = chise_char_id_parse_c_string (vp, len);
194   if ( *comb_char == -1 )
195     return -1;
196   return 0;
197 }
198
199 unsigned char*
200 chise_char_gets_feature_value (CHISE_Char_ID cid,
201                                CHISE_Feature feature,
202                                unsigned char* dst, size_t size)
203 {
204   unsigned char key_buf[8];
205
206   chise_format_char_id (cid, key_buf, 8);
207   return concord_obj_gets_feature_value (key_buf, feature, dst, size);
208 }
209
210 static int
211 (*chise_feature_for_a_char_with_value_func) (CHISE_Char_ID cid,
212                                              CHISE_Feature feature,
213                                              CHISE_Value* valdatum);
214
215 int
216 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
217                                                CONCORD_Feature feature,
218                                                CONCORD_String value);
219 int
220 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
221                                                CONCORD_Feature feature,
222                                                CONCORD_String value)
223 {
224   unsigned char* cid_str = CONCORD_String_data (object_id);
225   int cid_len = strnlen (cid_str, CONCORD_String_size (object_id));
226   CHISE_Char_ID cid = chise_char_id_parse_c_string (cid_str, cid_len);
227
228   return chise_feature_for_a_char_with_value_func (cid, feature, value);
229 }
230
231 int
232 chise_feature_foreach_char_with_value (CHISE_Feature feature,
233                                        int (*func) (CHISE_Char_ID cid,
234                                                     CHISE_Feature feature,
235                                                     CHISE_Value* valdatum))
236 {
237   chise_feature_for_a_char_with_value_func = func;
238   return
239     concord_feature_foreach_obj_string
240     (feature, &chise_feature_foreach_char_with_value_wrapper);
241 }
242
243
244 int
245 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
246 {
247   return concord_index_setup_db (ccs, writable);
248 }
249
250 int
251 chise_ccs_sync (CHISE_CCS ccs)
252 {
253   return concord_index_sync (ccs);
254 }
255
256 CHISE_Char_ID
257 chise_ccs_decode (CHISE_CCS ccs, int code_point)
258 {
259   char key_buf[16];
260   CONCORD_String_Tank value;
261   int status;
262
263   sprintf(key_buf, "%d", code_point);
264   status = concord_index_strid_get_obj_string (ccs, key_buf, &value);
265   if (!status)
266     {
267       unsigned char *str
268         = (unsigned char *)CONCORD_String_data (&value);
269       int len = strnlen (str, CONCORD_String_size (&value));
270
271       return chise_char_id_parse_c_string (str, len);
272     }
273   return -1;
274 }
275
276 int
277 chise_ccs_set_decoded_char (CHISE_CCS ccs,
278                             int code_point, CHISE_Char_ID cid)
279 {
280   char key_buf[16], val_buf[8];
281
282   sprintf(key_buf, "%d", code_point);
283   chise_format_char_id (cid, val_buf, 8);
284   return concord_index_strid_put_obj (ccs, key_buf, val_buf);
285 }
286
287
288 int
289 chise_property_setup_db (CHISE_Property property, int writable)
290 {
291   return concord_feature_setup_db (property, writable);
292 }
293
294 int
295 chise_property_sync (CHISE_Property property)
296 {
297   return concord_feature_sync (property);
298 }
299
300 int
301 chise_feature_set_property_value (CHISE_Feature feature,
302                                   CHISE_Property property,
303                                   unsigned char* value)
304 {
305   return
306     concord_obj_put_feature_value_str
307     (concord_feature_get_name (feature), property, value);
308 }
309
310 int
311 chise_feature_load_property_value (CHISE_Feature feature,
312                                    CHISE_Property property,
313                                    CHISE_Value* valdatum)
314 {
315   return
316     concord_obj_get_feature_value_string
317     (concord_feature_get_name (feature), property, valdatum);
318 }
319
320 unsigned char*
321 chise_feature_gets_property_value (CHISE_Feature feature,
322                                    CHISE_Property property,
323                                    unsigned char* buf, size_t size)
324 {
325   return
326     concord_obj_gets_feature_value (concord_feature_get_name (feature),
327                                     property, buf, size);
328 }
329
330
331 CHISE_Char_ID
332 chise_char_id_parse_c_string (unsigned char *str, size_t len)
333 {
334   int i = 0;
335
336   if ( (len >= 2) && (str[i++] == '?') )
337     {
338       unsigned char c = str[i++];
339       int counter;
340       CHISE_Char_ID cid;
341
342       if (c == '\\')
343         {
344           if (len < 3)
345             return -1;
346           c = str[i++];
347           if (c == '^')
348             {
349               if (len < 4)
350                 return -1;
351               c = str[i++];
352               if (c == '?')
353                 return 0x7F;
354               else
355                 return c & (0x80 | 0x1F);
356             }
357         }
358       if ( c < 0xC0 )
359         {
360           cid = c;
361           counter = 0;
362         }
363       else if ( c < 0xE0 )
364         {
365           cid = c & 0x1f;
366           counter = 1;
367         }
368       else if ( c < 0xF0 )
369         {
370           cid = c & 0x0f;
371           counter = 2;
372         }
373       else if ( c < 0xF8 )
374         {
375           cid = c & 0x07;
376           counter = 3;
377         }
378       else if ( c < 0xFC )
379         {
380           cid = c & 0x03;
381           counter = 4;
382         }
383       else
384         {
385           cid = c & 0x01;
386           counter = 5;
387         }
388
389       if (counter + 2 <= len)
390         {
391           int j;
392
393           for (j = 0; j < counter; j++)
394             cid = (cid << 6) | (str[j + i] & 0x3F);
395           return cid;
396         }
397     }
398   return -1;
399 }
400
401 int
402 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
403 {
404   int i = 0;
405
406   dest[i++] = '?';
407   if (cid == '\t')
408     {
409       dest[i++] = '\\';
410       dest[i++] = 't';
411       dest[i] = '\0';
412       return i;
413     }
414   else if (cid == '\n')
415     {
416       dest[i++] = '\\';
417       dest[i++] = 'n';
418       dest[i] = '\0';
419       return i;
420     }
421   else if (cid == '\r')
422     {
423       dest[i++] = '\\';
424       dest[i++] = 'r';
425       dest[i] = '\0';
426       return i;
427     }
428   else if (cid == 0x1C)
429     {
430       dest[i++] = '\\';
431       dest[i++] = '^';
432       dest[i++] = '\\';
433       dest[i++] = '\\';
434       dest[i] = '\0';
435       return i;
436     }
437   else if (cid <= 0x1F)
438     {
439       dest[i++] = '\\';
440       dest[i++] = '^';
441       dest[i++] = '@' + cid;
442       dest[i] = '\0';
443       return i;
444     }
445   else if ( (cid == ' ') || (cid == '"') ||
446             (cid == '#') || (cid == '\'') ||
447             (cid == '(') || (cid == ')') ||
448             (cid == ',') || (cid == '.') ||
449             (cid == ';') || (cid == '?') ||
450             (cid == '[') || (cid == '\\') ||
451             (cid == ']') || (cid == '`') )
452     {
453       dest[i++] = '\\';
454       dest[i++] = cid;
455       dest[i] = '\0';
456       return i;
457     }
458   else if (cid <= 0x7E)
459     {
460       dest[i++] = cid;
461       dest[i] = '\0';
462       return i;
463     }
464   else if (cid == 0x7F)
465     {
466       dest[i++] = '\\';
467       dest[i++] = '^';
468       dest[i++] = '?';
469       dest[i] = '\0';
470       return i;
471     }
472   else if (cid <= 0x9F)
473     {
474       dest[i++] = '\\';
475       dest[i++] = '^';
476       dest[i++] = ((cid + '@') >> 6) | 0xC0;
477       dest[i++] = ((cid + '@') & 0x3F) | 0x80;
478       dest[i] = '\0';
479       return i;
480     }
481   else if (cid <= 0x7FF)
482     {
483       dest[i++] = (cid >> 6) | 0xC0;
484       dest[i++] = (cid & 0x3F) | 0x80;
485       dest[i] = '\0';
486       return i;
487     }
488   else if (cid <= 0xFFFF)
489     {
490       dest[i++] = (cid >> 12) | 0xE0;
491       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
492       dest[i++]=  (cid        & 0x3F) | 0x80;
493       dest[i] = '\0';
494       return i;
495     }
496   else if (cid <= 0x1FFFFF)
497     {
498       dest[i++]=  (cid >> 18) | 0xF0;
499       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
500       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
501       dest[i++]=  (cid        & 0x3F) | 0x80;
502       dest[i] = '\0';
503       return i;
504     }
505   else if (cid <= 0x3FFFFFF)
506     {
507       dest[i++]=  (cid >> 24) | 0xF8;
508       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
509       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
510       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
511       dest[i++]=  (cid        & 0x3F) | 0x80;
512       dest[i] = '\0';
513       return i;
514     }
515   else
516     {
517       dest[i++]=  (cid >> 30) | 0xFC;
518       dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
519       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
520       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
521       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
522       dest[i++]=  (cid        & 0x3F) | 0x80;
523       dest[i] = '\0';
524       return i;
525     }
526 }