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