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