Move strnlen related code from chise.h to chise.c.
[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 <= 0x7f)
174     {
175       key_buf[1] = cid;
176       key_buf[2] = '\0';
177     }
178   else if (cid <= 0x7ff)
179     {
180       key_buf[1] = (cid >> 6) | 0xc0;
181       key_buf[2] = (cid & 0x3f) | 0x80;
182       key_buf[3] = '\0';
183     }
184   else if (cid <= 0xffff)
185     {
186       key_buf[1] = (cid >> 12) | 0xe0;
187       key_buf[2]= ((cid >>  6) & 0x3f) | 0x80;
188       key_buf[3]=  (cid        & 0x3f) | 0x80;
189       key_buf[4] = '\0';
190     }
191   else if (cid <= 0x1fffff)
192     {
193       key_buf[1]=  (cid >> 18) | 0xf0;
194       key_buf[2]= ((cid >> 12) & 0x3f) | 0x80;
195       key_buf[3]= ((cid >>  6) & 0x3f) | 0x80;
196       key_buf[4]=  (cid        & 0x3f) | 0x80;
197       key_buf[5] = '\0';
198     }
199   else if (cid <= 0x3ffffff)
200     {
201       key_buf[1]=  (cid >> 24) | 0xf8;
202       key_buf[2]= ((cid >> 18) & 0x3f) | 0x80;
203       key_buf[3]= ((cid >> 12) & 0x3f) | 0x80;
204       key_buf[4]= ((cid >>  6) & 0x3f) | 0x80;
205       key_buf[5]=  (cid        & 0x3f) | 0x80;
206       key_buf[6] = '\0';
207     }
208   else
209     {
210       key_buf[1]=  (cid >> 30) | 0xfc;
211       key_buf[2]= ((cid >> 24) & 0x3f) | 0x80;
212       key_buf[3]= ((cid >> 18) & 0x3f) | 0x80;
213       key_buf[4]= ((cid >> 12) & 0x3f) | 0x80;
214       key_buf[5]= ((cid >>  6) & 0x3f) | 0x80;
215       key_buf[6]=  (cid        & 0x3f) | 0x80;
216       key_buf[7] = '\0';
217     }
218   return
219     chise_get_attribute_table (db, key_buf, valdatum);
220 }
221
222
223 int
224 chise_open_attribute_table (CHISE_Attribute_Table **db,
225                             const char *db_dir,
226                             const char *encoding, const char *feature,
227                             DBTYPE real_subtype,
228                             u_int32_t accessmask, int modemask)
229 {
230   DB* dbase;
231   int status;
232   int len;
233   int size;
234   char *db_file_name;
235
236   status = db_create (&dbase, NULL, 0);
237   if (status)
238     return -1;
239
240   len = strlen (db_dir);
241   size = len + strlen (encoding) + strlen (feature) + 4;
242   db_file_name = alloca (size);
243   strcpy (db_file_name, db_dir);
244   if (db_file_name[len - 1] != '/')
245     {
246       db_file_name[len++] = '/';
247       db_file_name[len] = '\0';
248     }
249   strcat (db_file_name, encoding);
250   strcat (db_file_name, "/");
251   strcat (db_file_name, feature);
252   status = dbase->open (dbase, db_file_name, NULL,
253                         real_subtype, accessmask, modemask);
254   if (status)
255     {
256       dbase->close (dbase, 0);
257       return -1;
258     }
259   *db = dbase;
260   return 0;
261 }
262
263 int
264 chise_close_attribute_table (CHISE_Attribute_Table *db)
265 {
266   if (db)
267     {
268       db->sync  (db, 0);
269       db->close (db, 0);
270     }
271   return 0;
272 }
273
274 int
275 chise_get_attribute_table (CHISE_Attribute_Table *db,
276                            char *key, CHISE_Value *valdatum)
277 {
278   DBT keydatum;
279   int status = 0;
280
281   /* DB Version 2 requires DBT's to be zeroed before use. */
282   xzero (keydatum);
283   xzero (*valdatum);
284
285   keydatum.data = key;
286   keydatum.size = strlen (key);
287
288   status = db->get (db, NULL, &keydatum, valdatum, 0);
289   return status;
290 }