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   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 int
156 chise_char_load_decomposition (CHISE_Char_ID cid,
157                                CHISE_Feature feature,
158                                CHISE_Char_ID* base_char, CHISE_Char_ID* comb_char)
159 {
160   unsigned char key_buf[8];
161   CHISE_Value value;
162   int status;
163   unsigned char* vp;
164   unsigned char* vp_ret;
165   int len;
166
167   chise_format_char_id (cid, key_buf, 8);
168   if ( status = concord_obj_get_feature_value_string (key_buf, feature, &value) )
169     return status;
170   len = chise_value_size (&value);
171   if ( len < (1 + 2 + 1 + 2 + 1) )
172     return -1;
173
174   vp = chise_value_data (&value);
175   if ( *vp++ != '(' )
176     return -1;
177   len--;
178
179   if ( ( vp_ret = memchr (vp, ' ', len) ) == NULL )
180     return -1;
181   *base_char = chise_char_id_parse_c_string (vp, vp_ret - vp + 1);
182   if ( *base_char == -1 )
183     return -1;
184   vp = vp_ret + 1;
185   len -= vp - chise_value_data (&value);
186   if ( len <= 1 )
187     return -1;
188
189   *comb_char = chise_char_id_parse_c_string (vp, len);
190   if ( *comb_char == -1 )
191     return -1;
192   return 0;
193 }
194
195 unsigned char*
196 chise_char_gets_feature_value (CHISE_Char_ID cid,
197                                CHISE_Feature feature,
198                                unsigned char* dst, size_t size)
199 {
200   unsigned char key_buf[8];
201
202   chise_format_char_id (cid, key_buf, 8);
203   return concord_obj_gets_feature_value (key_buf, feature, dst, size);
204 }
205
206 static int
207 (*chise_feature_for_a_char_with_value_func) (CHISE_Char_ID cid,
208                                              CHISE_Feature feature,
209                                              CHISE_Value* valdatum);
210
211 int
212 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
213                                                CONCORD_Feature feature,
214                                                CONCORD_String value);
215 int
216 chise_feature_foreach_char_with_value_wrapper (CONCORD_String object_id,
217                                                CONCORD_Feature feature,
218                                                CONCORD_String value)
219 {
220   unsigned char* cid_str = CONCORD_String_data (object_id);
221   int cid_len = strnlen (cid_str, CONCORD_String_size (object_id));
222   CHISE_Char_ID cid = chise_char_id_parse_c_string (cid_str, cid_len);
223
224   return chise_feature_for_a_char_with_value_func (cid, feature, value);
225 }
226
227 int
228 chise_feature_foreach_char_with_value (CHISE_Feature feature,
229                                        int (*func) (CHISE_Char_ID cid,
230                                                     CHISE_Feature feature,
231                                                     CHISE_Value* valdatum))
232 {
233   chise_feature_for_a_char_with_value_func = func;
234   return
235     concord_feature_foreach_obj_string
236     (feature, &chise_feature_foreach_char_with_value_wrapper);
237 }
238
239
240 int
241 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
242 {
243   return concord_index_setup_db (ccs, writable);
244 }
245
246 int
247 chise_ccs_sync (CHISE_CCS ccs)
248 {
249   return concord_index_sync (ccs);
250 }
251
252 CHISE_Char_ID
253 chise_ccs_decode (CHISE_CCS ccs, int code_point)
254 {
255   char key_buf[16];
256   CONCORD_String_Tank value;
257   int status;
258
259   sprintf(key_buf, "%d", code_point);
260   status = concord_index_strid_get_obj_string (ccs, key_buf, &value);
261   if (!status)
262     {
263       unsigned char *str
264         = (unsigned char *)CONCORD_String_data (&value);
265       int len = strnlen (str, CONCORD_String_size (&value));
266
267       return chise_char_id_parse_c_string (str, len);
268     }
269   return -1;
270 }
271
272 int
273 chise_ccs_set_decoded_char (CHISE_CCS ccs,
274                             int code_point, CHISE_Char_ID cid)
275 {
276   char key_buf[16], val_buf[8];
277
278   sprintf(key_buf, "%d", code_point);
279   chise_format_char_id (cid, val_buf, 8);
280   return concord_index_strid_put_obj (ccs, key_buf, val_buf);
281 }
282
283
284 int
285 chise_property_setup_db (CHISE_Property property, int writable)
286 {
287   return concord_feature_setup_db (property, writable);
288 }
289
290 int
291 chise_property_sync (CHISE_Property property)
292 {
293   return concord_feature_sync (property);
294 }
295
296 int
297 chise_feature_set_property_value (CHISE_Feature feature,
298                                   CHISE_Property property,
299                                   unsigned char* value)
300 {
301   return
302     concord_obj_put_feature_value_str
303     (concord_feature_get_name (feature), property, value);
304 }
305
306 int
307 chise_feature_load_property_value (CHISE_Feature feature,
308                                    CHISE_Property property,
309                                    CHISE_Value* valdatum)
310 {
311   return
312     concord_obj_get_feature_value_string
313     (concord_feature_get_name (feature), property, valdatum);
314 }
315
316 unsigned char*
317 chise_feature_gets_property_value (CHISE_Feature feature,
318                                    CHISE_Property property,
319                                    unsigned char* buf, size_t size)
320 {
321   return
322     concord_obj_gets_feature_value (concord_feature_get_name (feature),
323                                     property, buf, size);
324 }
325
326
327 CHISE_Char_ID
328 chise_char_id_parse_c_string (unsigned char *str, size_t len)
329 {
330   int i = 0;
331
332   if ( (len >= 2) && (str[i++] == '?') )
333     {
334       unsigned char c = str[i++];
335       int counter;
336       CHISE_Char_ID cid;
337
338       if (c == '\\')
339         {
340           if (len < 3)
341             return -1;
342           c = str[i++];
343           if (c == '^')
344             {
345               if (len < 4)
346                 return -1;
347               c = str[i++];
348               if (c == '?')
349                 return 0x7F;
350               else
351                 return c & (0x80 | 0x1F);
352             }
353         }
354       if ( c < 0xC0 )
355         {
356           cid = c;
357           counter = 0;
358         }
359       else if ( c < 0xE0 )
360         {
361           cid = c & 0x1f;
362           counter = 1;
363         }
364       else if ( c < 0xF0 )
365         {
366           cid = c & 0x0f;
367           counter = 2;
368         }
369       else if ( c < 0xF8 )
370         {
371           cid = c & 0x07;
372           counter = 3;
373         }
374       else if ( c < 0xFC )
375         {
376           cid = c & 0x03;
377           counter = 4;
378         }
379       else
380         {
381           cid = c & 0x01;
382           counter = 5;
383         }
384
385       if (counter + 2 <= len)
386         {
387           int j;
388
389           for (j = 0; j < counter; j++)
390             cid = (cid << 6) | (str[j + i] & 0x3F);
391           return cid;
392         }
393     }
394   return -1;
395 }
396
397 int
398 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
399 {
400   int i = 0;
401
402   dest[i++] = '?';
403   if (cid == '\t')
404     {
405       dest[i++] = '\\';
406       dest[i++] = 't';
407       dest[i] = '\0';
408       return i;
409     }
410   else if (cid == '\n')
411     {
412       dest[i++] = '\\';
413       dest[i++] = 'n';
414       dest[i] = '\0';
415       return i;
416     }
417   else if (cid == '\r')
418     {
419       dest[i++] = '\\';
420       dest[i++] = 'r';
421       dest[i] = '\0';
422       return i;
423     }
424   else if (cid == 0x1C)
425     {
426       dest[i++] = '\\';
427       dest[i++] = '^';
428       dest[i++] = '\\';
429       dest[i++] = '\\';
430       dest[i] = '\0';
431       return i;
432     }
433   else if (cid <= 0x1F)
434     {
435       dest[i++] = '\\';
436       dest[i++] = '^';
437       dest[i++] = '@' + cid;
438       dest[i] = '\0';
439       return i;
440     }
441   else if ( (cid == ' ') || (cid == '"') ||
442             (cid == '#') || (cid == '\'') ||
443             (cid == '(') || (cid == ')') ||
444             (cid == ',') || (cid == '.') ||
445             (cid == ';') || (cid == '?') ||
446             (cid == '[') || (cid == '\\') ||
447             (cid == ']') || (cid == '`') )
448     {
449       dest[i++] = '\\';
450       dest[i++] = cid;
451       dest[i] = '\0';
452       return i;
453     }
454   else if (cid <= 0x7E)
455     {
456       dest[i++] = cid;
457       dest[i] = '\0';
458       return i;
459     }
460   else if (cid == 0x7F)
461     {
462       dest[i++] = '\\';
463       dest[i++] = '^';
464       dest[i++] = '?';
465       dest[i] = '\0';
466       return i;
467     }
468   else if (cid <= 0x9F)
469     {
470       dest[i++] = '\\';
471       dest[i++] = '^';
472       dest[i++] = ((cid + '@') >> 6) | 0xC0;
473       dest[i++] = ((cid + '@') & 0x3F) | 0x80;
474       dest[i] = '\0';
475       return i;
476     }
477   else if (cid <= 0x7FF)
478     {
479       dest[i++] = (cid >> 6) | 0xC0;
480       dest[i++] = (cid & 0x3F) | 0x80;
481       dest[i] = '\0';
482       return i;
483     }
484   else if (cid <= 0xFFFF)
485     {
486       dest[i++] = (cid >> 12) | 0xE0;
487       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
488       dest[i++]=  (cid        & 0x3F) | 0x80;
489       dest[i] = '\0';
490       return i;
491     }
492   else if (cid <= 0x1FFFFF)
493     {
494       dest[i++]=  (cid >> 18) | 0xF0;
495       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
496       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
497       dest[i++]=  (cid        & 0x3F) | 0x80;
498       dest[i] = '\0';
499       return i;
500     }
501   else if (cid <= 0x3FFFFFF)
502     {
503       dest[i++]=  (cid >> 24) | 0xF8;
504       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
505       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
506       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
507       dest[i++]=  (cid        & 0x3F) | 0x80;
508       dest[i] = '\0';
509       return i;
510     }
511   else
512     {
513       dest[i++]=  (cid >> 30) | 0xFC;
514       dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
515       dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
516       dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
517       dest[i++]= ((cid >>  6) & 0x3F) | 0x80;
518       dest[i++]=  (cid        & 0x3F) | 0x80;
519       dest[i] = '\0';
520       return i;
521     }
522 }