(chise_ft_iterate): New function.
[chise/libchise.git] / chise.c
1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4
5 #ifndef HAVE_STRNLEN
6 /* original in mysql, strings/strnlen.c.
7 uint strnlen(register const char *s, register uint maxlen)
8 {
9   const char *end= (const char *)memchr(s, '\0', maxlen);
10   return end ? (uint) (end - s) : maxlen;
11 }
12 */
13 static inline int
14 strnlen (register const char *s, register int maxlen)
15 {
16   const char *end= (const char *)memchr(s, '\0', maxlen);
17   return end ? (int) (end - s) : maxlen;
18 }
19 #endif
20
21 #include "chise.h"
22
23 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
24
25
26 int
27 chise_open_data_source (CHISE_DS *ds, CHISE_DS_Type type, char *location)
28 {
29   ds->type = type;
30   ds->location = location;
31   return 0;
32 }
33
34 int
35 chise_close_data_source (CHISE_DS *ds)
36 {
37   ds->type = CHISE_DS_NONE;
38   ds->location = NULL;
39   return 0;
40 }
41
42
43 int
44 chise_open_decoding_table (CHISE_Decoding_Table **db,
45                            CHISE_DS *ds, const char *ccs,
46                            DBTYPE real_subtype,
47                            u_int32_t accessmask, int modemask)
48 {
49   return
50     chise_open_attribute_table (db, ds->location,
51                                 ccs, "system-char-id",
52                                 real_subtype, accessmask, modemask);
53 }
54
55 int
56 chise_close_decoding_table (CHISE_Decoding_Table *db)
57 {
58   if (db)
59     return chise_close_attribute_table (db);
60   return -1;
61 }
62
63 CHISE_Char_ID
64 chise_dt_get_char (CHISE_Decoding_Table *db, int code_point)
65 {
66   CHISE_Value valdatum;
67   int status = 0;
68   char key_buf[16];
69
70   sprintf(key_buf, "%d", code_point);
71   status = chise_get_attribute_table (db, key_buf, &valdatum);
72   if (!status)
73     {
74       unsigned char *str
75         = (unsigned char *)chise_value_data (&valdatum);
76       int len = strnlen (str, chise_value_size (&valdatum));
77       int i = 0;
78
79       if ( (len >= 2) && (str[i++] == '?') )
80         {
81           unsigned char c = str[i++];
82           int counter;
83           CHISE_Char_ID cid;
84
85           if (c == '\\')
86             {
87               if (len < 3)
88                 return -1;
89               c = str[i++];
90               if (c == '^')
91                 {
92                   if (len < 4)
93                     return -1;
94                   c = str[i++];
95                   if (c == '?')
96                     return 0x7F;
97                   else
98                     return c & (0x80 | 0x1F);
99                 }
100             }
101           if ( c < 0xC0 )
102             {
103               cid = c;
104               counter = 0;
105             }
106           else if ( c < 0xE0 )
107             {
108               cid = c & 0x1f;
109               counter = 1;
110             }
111           else if ( c < 0xF0 )
112             {
113               cid = c & 0x0f;
114               counter = 2;
115             }
116           else if ( c < 0xF8 )
117             {
118               cid = c & 0x07;
119               counter = 3;
120             }
121           else if ( c < 0xFC )
122             {
123               cid = c & 0x03;
124               counter = 4;
125             }
126           else
127             {
128               cid = c & 0x01;
129               counter = 5;
130             }
131
132           if (counter + 2 <= len)
133             {
134               int j;
135
136               for (j = 0; j < counter; j++)
137                 cid = (cid << 6) | (str[j + i] & 0x3F);
138               return cid;
139             }
140         }
141     }
142   return -1;
143 }
144
145
146
147 int
148 chise_open_feature_table (CHISE_Feature_Table **db,
149                           CHISE_DS *ds, const char *feature,
150                           DBTYPE real_subtype,
151                           u_int32_t accessmask, int modemask)
152 {
153   return
154     chise_open_attribute_table (db, ds->location,
155                                 "system-char-id", feature,
156                                 real_subtype, accessmask, modemask);
157 }
158
159 int
160 chise_close_feature_table (CHISE_Feature_Table *db)
161 {
162   if (db)
163     return chise_close_attribute_table (db);
164   return -1;
165 }
166
167 int chise_ft_get_value (CHISE_Feature_Table *db,
168                         CHISE_Char_ID cid, CHISE_Value *valdatum)
169 {
170   unsigned char key_buf[8];
171
172   key_buf[0] = '?';
173   if (cid == '\t')
174     {
175       key_buf[1] = '\\';
176       key_buf[2] = 't';
177       key_buf[3] = '\0';
178     }
179   else if (cid == '\n')
180     {
181       key_buf[1] = '\\';
182       key_buf[2] = 'n';
183       key_buf[3] = '\0';
184     }
185   else if (cid == '\r')
186     {
187       key_buf[1] = '\\';
188       key_buf[2] = 'r';
189       key_buf[3] = '\0';
190     }
191   else if (cid == 0x1C)
192     {
193       key_buf[1] = '\\';
194       key_buf[2] = '^';
195       key_buf[3] = '\\';
196       key_buf[4] = '\\';
197       key_buf[5] = '\0';
198     }
199   else if (cid <= 0x1F)
200     {
201       key_buf[1] = '\\';
202       key_buf[2] = '^';
203       key_buf[3] = '@' + cid;
204       key_buf[4] = '\0';
205     }
206   else if ( (cid == ' ') || (cid == '"') ||
207             (cid == '#') || (cid == '\'') ||
208             (cid == '(') || (cid == ')') ||
209             (cid == ',') || (cid == '.') ||
210             (cid == ';') || (cid == '?') ||
211             (cid == '[') || (cid == '\\') ||
212             (cid == ']') || (cid == '`') )
213     {
214       key_buf[1] = '\\';
215       key_buf[2] = cid;
216       key_buf[3] = '\0';
217     }
218   else if (cid <= 0x7E)
219     {
220       key_buf[1] = cid;
221       key_buf[2] = '\0';
222     }
223   else if (cid == 0x7F)
224     {
225       key_buf[1] = '\\';
226       key_buf[2] = '^';
227       key_buf[3] = '?';
228       key_buf[4] = '\0';
229     }
230   else if (cid <= 0x9F)
231     {
232       key_buf[1] = '\\';
233       key_buf[2] = '^';
234       key_buf[3] = ((cid + '@') >> 6) | 0xC0;
235       key_buf[4] = ((cid + '@') & 0x3F) | 0x80;
236       key_buf[5] = '\0';
237
238     }
239   else if (cid <= 0x7FF)
240     {
241       key_buf[1] = (cid >> 6) | 0xC0;
242       key_buf[2] = (cid & 0x3F) | 0x80;
243       key_buf[3] = '\0';
244     }
245   else if (cid <= 0xFFFF)
246     {
247       key_buf[1] = (cid >> 12) | 0xE0;
248       key_buf[2]= ((cid >>  6) & 0x3F) | 0x80;
249       key_buf[3]=  (cid        & 0x3F) | 0x80;
250       key_buf[4] = '\0';
251     }
252   else if (cid <= 0x1FFFFF)
253     {
254       key_buf[1]=  (cid >> 18) | 0xF0;
255       key_buf[2]= ((cid >> 12) & 0x3F) | 0x80;
256       key_buf[3]= ((cid >>  6) & 0x3F) | 0x80;
257       key_buf[4]=  (cid        & 0x3F) | 0x80;
258       key_buf[5] = '\0';
259     }
260   else if (cid <= 0x3FFFFFF)
261     {
262       key_buf[1]=  (cid >> 24) | 0xF8;
263       key_buf[2]= ((cid >> 18) & 0x3F) | 0x80;
264       key_buf[3]= ((cid >> 12) & 0x3F) | 0x80;
265       key_buf[4]= ((cid >>  6) & 0x3F) | 0x80;
266       key_buf[5]=  (cid        & 0x3F) | 0x80;
267       key_buf[6] = '\0';
268     }
269   else
270     {
271       key_buf[1]=  (cid >> 30) | 0xFC;
272       key_buf[2]= ((cid >> 24) & 0x3F) | 0x80;
273       key_buf[3]= ((cid >> 18) & 0x3F) | 0x80;
274       key_buf[4]= ((cid >> 12) & 0x3F) | 0x80;
275       key_buf[5]= ((cid >>  6) & 0x3F) | 0x80;
276       key_buf[6]=  (cid        & 0x3F) | 0x80;
277       key_buf[7] = '\0';
278     }
279   return
280     chise_get_attribute_table (db, key_buf, valdatum);
281 }
282
283
284 int
285 chise_open_attribute_table (CHISE_Attribute_Table **db,
286                             const char *db_dir,
287                             const char *encoding, const char *feature,
288                             DBTYPE real_subtype,
289                             u_int32_t accessmask, int modemask)
290 {
291   DB* dbase;
292   int status;
293   int len, flen, i;
294   int size;
295   char *db_file_name, *sp;
296
297   status = db_create (&dbase, NULL, 0);
298   if (status)
299     return -1;
300
301   len = strlen (db_dir);
302   flen = strlen (feature);
303   size = len + strlen (encoding) + flen * 3 + 4;
304   db_file_name = alloca (size);
305   strcpy (db_file_name, db_dir);
306   if (db_file_name[len - 1] != '/')
307     {
308       db_file_name[len++] = '/';
309       db_file_name[len] = '\0';
310     }
311   strcat (db_file_name, encoding);
312   strcat (db_file_name, "/");
313   /* strcat (db_file_name, feature); */
314   sp = &db_file_name[strlen (db_file_name)];
315   for (i = 0; i < flen; i++)
316     {
317       int c = feature[i];
318
319       if ( (c == '/') || (c == '%') )
320         {
321           sprintf (sp, "%%%02X", c);
322           sp += 3;
323         }
324       else
325         *sp++ = c;
326     }
327   *sp = '\0';
328   status = dbase->open (dbase, db_file_name, NULL,
329                         real_subtype, accessmask, modemask);
330   if (status)
331     {
332       dbase->close (dbase, 0);
333       return -1;
334     }
335   *db = dbase;
336   return 0;
337 }
338
339 int
340 chise_close_attribute_table (CHISE_Attribute_Table *db)
341 {
342   if (db)
343     {
344       db->sync  (db, 0);
345       db->close (db, 0);
346     }
347   return 0;
348 }
349
350 int
351 chise_get_attribute_table (CHISE_Attribute_Table *db,
352                            char *key, CHISE_Value *valdatum)
353 {
354   DBT keydatum;
355   int status = 0;
356
357   /* DB Version 2 requires DBT's to be zeroed before use. */
358   xzero (keydatum);
359   xzero (*valdatum);
360
361   keydatum.data = key;
362   keydatum.size = strlen (key);
363
364   status = db->get (db, NULL, &keydatum, valdatum, 0);
365   return status;
366 }