6e8bb4650d0a09b15f87e907100d81ed45abcdb7
[chise/libchise.git] / chise.c
1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4
5 #include "chise.h"
6
7 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
8
9
10 int
11 chise_open_data_source (CHISE_DS *ds, CHISE_DS_Type type, char *location)
12 {
13   ds->type = type;
14   ds->location = location;
15   return 0;
16 }
17
18 int
19 chise_close_data_source (CHISE_DS *ds)
20 {
21   ds->type = CHISE_DS_NONE;
22   ds->location = NULL;
23   return 0;
24 }
25
26
27 int
28 chise_open_decoding_table (CHISE_Decoding_Table **db,
29                            CHISE_DS *ds, const char *ccs,
30                            DBTYPE real_subtype,
31                            u_int32_t accessmask, int modemask)
32 {
33   return
34     chise_open_attribute_table (db, ds->location,
35                                 ccs, "system-char-id",
36                                 real_subtype, accessmask, modemask);
37 }
38
39 int
40 chise_close_decoding_table (CHISE_Decoding_Table *db)
41 {
42   if (db)
43     return chise_close_attribute_table (db);
44   return -1;
45 }
46
47 CHISE_Char_ID
48 chise_dt_get_char (CHISE_Decoding_Table *db, int code_point)
49 {
50   CHISE_Value valdatum;
51   int status = 0;
52   char key_buf[16];
53
54   sprintf(key_buf, "%d", code_point);
55   status = chise_get_attribute_table (db, key_buf, &valdatum);
56   if (!status)
57     {
58       unsigned char *str
59         = (unsigned char *)chise_value_data (&valdatum);
60       int len = strnlen (str, chise_value_size (&valdatum));
61       int i = 0;
62
63       if ( (len >= 2) && (str[i++] == '?') )
64         {
65           unsigned char c = str[i++];
66           int counter;
67           CHISE_Char_ID cid;
68
69           if (c == '\\')
70             {
71               if (len < 3)
72                 return -1;
73               c = str[i++];
74               if (c == '^')
75                 {
76                   if (len < 4)
77                     return -1;
78                   c = str[i++];
79                   if (c == '?')
80                     return 0x7F;
81                   else
82                     return c & (0x80 | 0x1F);
83                 }
84             }
85           if ( c < 0xC0 )
86             {
87               cid = c;
88               counter = 0;
89             }
90           else if ( c < 0xE0 )
91             {
92               cid = c & 0x1f;
93               counter = 1;
94             }
95           else if ( c < 0xF0 )
96             {
97               cid = c & 0x0f;
98               counter = 2;
99             }
100           else if ( c < 0xF8 )
101             {
102               cid = c & 0x07;
103               counter = 3;
104             }
105           else if ( c < 0xFC )
106             {
107               cid = c & 0x03;
108               counter = 4;
109             }
110           else
111             {
112               cid = c & 0x01;
113               counter = 5;
114             }
115
116           if (counter + 2 <= len)
117             {
118               int j;
119
120               for (j = 0; j < counter; j++)
121                 cid = (cid << 6) | (str[j + i] & 0x3F);
122               return cid;
123             }
124         }
125     }
126   return -1;
127 }
128
129
130
131 int
132 chise_open_feature_table (CHISE_Feature_Table **db,
133                           CHISE_DS *ds, const char *feature,
134                           DBTYPE real_subtype,
135                           u_int32_t accessmask, int modemask)
136 {
137   return
138     chise_open_attribute_table (db, ds->location,
139                                 "system-char-id", feature,
140                                 real_subtype, accessmask, modemask);
141 }
142
143 int
144 chise_close_feature_table (CHISE_Feature_Table *db)
145 {
146   if (db)
147     return chise_close_attribute_table (db);
148   return -1;
149 }
150
151 int chise_ft_get_value (CHISE_Feature_Table *db,
152                         CHISE_Char_ID cid, CHISE_Value *valdatum)
153 {
154   unsigned char key_buf[8];
155
156   key_buf[0] = '?';
157   if (cid <= 0x7f)
158     {
159       key_buf[1] = cid;
160       key_buf[2] = '\0';
161     }
162   else if (cid <= 0x7ff)
163     {
164       key_buf[1] = (cid >> 6) | 0xc0;
165       key_buf[2] = (cid & 0x3f) | 0x80;
166       key_buf[3] = '\0';
167     }
168   else if (cid <= 0xffff)
169     {
170       key_buf[1] = (cid >> 12) | 0xe0;
171       key_buf[2]= ((cid >>  6) & 0x3f) | 0x80;
172       key_buf[3]=  (cid        & 0x3f) | 0x80;
173       key_buf[4] = '\0';
174     }
175   else if (cid <= 0x1fffff)
176     {
177       key_buf[1]=  (cid >> 18) | 0xf0;
178       key_buf[2]= ((cid >> 12) & 0x3f) | 0x80;
179       key_buf[3]= ((cid >>  6) & 0x3f) | 0x80;
180       key_buf[4]=  (cid        & 0x3f) | 0x80;
181       key_buf[5] = '\0';
182     }
183   else if (cid <= 0x3ffffff)
184     {
185       key_buf[1]=  (cid >> 24) | 0xf8;
186       key_buf[2]= ((cid >> 18) & 0x3f) | 0x80;
187       key_buf[3]= ((cid >> 12) & 0x3f) | 0x80;
188       key_buf[4]= ((cid >>  6) & 0x3f) | 0x80;
189       key_buf[5]=  (cid        & 0x3f) | 0x80;
190       key_buf[6] = '\0';
191     }
192   else
193     {
194       key_buf[1]=  (cid >> 30) | 0xfc;
195       key_buf[2]= ((cid >> 24) & 0x3f) | 0x80;
196       key_buf[3]= ((cid >> 18) & 0x3f) | 0x80;
197       key_buf[4]= ((cid >> 12) & 0x3f) | 0x80;
198       key_buf[5]= ((cid >>  6) & 0x3f) | 0x80;
199       key_buf[6]=  (cid        & 0x3f) | 0x80;
200       key_buf[7] = '\0';
201     }
202   return
203     chise_get_attribute_table (db, key_buf, valdatum);
204 }
205
206
207 int
208 chise_open_attribute_table (CHISE_Attribute_Table **db,
209                             const char *db_dir,
210                             const char *encoding, const char *feature,
211                             DBTYPE real_subtype,
212                             u_int32_t accessmask, int modemask)
213 {
214   DB* dbase;
215   int status;
216   int len;
217   int size;
218   char *db_file_name;
219
220   status = db_create (&dbase, NULL, 0);
221   if (status)
222     return -1;
223
224   len = strlen (db_dir);
225   size = len + strlen (encoding) + strlen (feature) + 4;
226   db_file_name = alloca (size);
227   strcpy (db_file_name, db_dir);
228   if (db_file_name[len - 1] != '/')
229     {
230       db_file_name[len++] = '/';
231       db_file_name[len] = '\0';
232     }
233   strcat (db_file_name, encoding);
234   strcat (db_file_name, "/");
235   strcat (db_file_name, feature);
236   status = dbase->open (dbase, db_file_name, NULL,
237                         real_subtype, accessmask, modemask);
238   if (status)
239     {
240       dbase->close (dbase, 0);
241       return -1;
242     }
243   *db = dbase;
244   return 0;
245 }
246
247 int
248 chise_close_attribute_table (CHISE_Attribute_Table *db)
249 {
250   if (db)
251     {
252       db->sync  (db, 0);
253       db->close (db, 0);
254     }
255   return 0;
256 }
257
258 int
259 chise_get_attribute_table (CHISE_Attribute_Table *db,
260                            char *key, CHISE_Value *valdatum)
261 {
262   DBT keydatum;
263   int status = 0;
264
265   /* DB Version 2 requires DBT's to be zeroed before use. */
266   xzero (keydatum);
267   xzero (*valdatum);
268
269   keydatum.data = key;
270   keydatum.size = strlen (key);
271
272   status = db->get (db, NULL, &keydatum, valdatum, 0);
273   return status;
274 }