04b504181893c5ded74f8a0c95744a8bfaff2c2d
[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_data (&valdatum);
56       int len = strnlen (str, chise_value_size (&valdatum));
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               if (c == '^')
71                 {
72                   if (len < 4)
73                     return -1;
74                   c = str[i++];
75                   if (c == '?')
76                     return 0x7F;
77                   else
78                     return c & (0x80 | 0x1F);
79                 }
80             }
81           if ( c < 0xC0 )
82             {
83               cid = c;
84               counter = 0;
85             }
86           else if ( c < 0xE0 )
87             {
88               cid = c & 0x1f;
89               counter = 1;
90             }
91           else if ( c < 0xF0 )
92             {
93               cid = c & 0x0f;
94               counter = 2;
95             }
96           else if ( c < 0xF8 )
97             {
98               cid = c & 0x07;
99               counter = 3;
100             }
101           else if ( c < 0xFC )
102             {
103               cid = c & 0x03;
104               counter = 4;
105             }
106           else
107             {
108               cid = c & 0x01;
109               counter = 5;
110             }
111
112           if (counter + 2 <= len)
113             {
114               int j;
115
116               for (j = 0; j < counter; j++)
117                 cid = (cid << 6) | (str[j + i] & 0x3F);
118               return cid;
119             }
120         }
121     }
122   return -1;
123 }
124
125
126
127 int
128 chise_open_feature_table (CHISE_Feature_Table **db,
129                           CHISE_DS *ds, const char *feature,
130                           DBTYPE real_subtype,
131                           u_int32_t accessmask, int modemask)
132 {
133   return
134     chise_open_attribute_table (db, ds->location,
135                                 "system-char-id", feature,
136                                 real_subtype, accessmask, modemask);
137 }
138
139 int
140 chise_close_feature_table (CHISE_Feature_Table *db)
141 {
142   if (db)
143     return chise_close_attribute_table (db);
144   return -1;
145 }
146
147 int chise_ft_get_value (CHISE_Feature_Table *db,
148                         CHISE_Char_ID cid, CHISE_Value *valdatum)
149 {
150   unsigned char key_buf[8];
151
152   key_buf[0] = '?';
153   if (cid <= 0x7f)
154     {
155       key_buf[1] = cid;
156       key_buf[2] = '\0';
157     }
158   else if (cid <= 0x7ff)
159     {
160       key_buf[1] = (cid >> 6) | 0xc0;
161       key_buf[2] = (cid & 0x3f) | 0x80;
162       key_buf[3] = '\0';
163     }
164   else if (cid <= 0xffff)
165     {
166       key_buf[1] = (cid >> 12) | 0xe0;
167       key_buf[2]= ((cid >>  6) & 0x3f) | 0x80;
168       key_buf[3]=  (cid        & 0x3f) | 0x80;
169       key_buf[4] = '\0';
170     }
171   else if (cid <= 0x1fffff)
172     {
173       key_buf[1]=  (cid >> 18) | 0xf0;
174       key_buf[2]= ((cid >> 12) & 0x3f) | 0x80;
175       key_buf[3]= ((cid >>  6) & 0x3f) | 0x80;
176       key_buf[4]=  (cid        & 0x3f) | 0x80;
177       key_buf[5] = '\0';
178     }
179   else if (cid <= 0x3ffffff)
180     {
181       key_buf[1]=  (cid >> 24) | 0xf8;
182       key_buf[2]= ((cid >> 18) & 0x3f) | 0x80;
183       key_buf[3]= ((cid >> 12) & 0x3f) | 0x80;
184       key_buf[4]= ((cid >>  6) & 0x3f) | 0x80;
185       key_buf[5]=  (cid        & 0x3f) | 0x80;
186       key_buf[6] = '\0';
187     }
188   else
189     {
190       key_buf[1]=  (cid >> 30) | 0xfc;
191       key_buf[2]= ((cid >> 24) & 0x3f) | 0x80;
192       key_buf[3]= ((cid >> 18) & 0x3f) | 0x80;
193       key_buf[4]= ((cid >> 12) & 0x3f) | 0x80;
194       key_buf[5]= ((cid >>  6) & 0x3f) | 0x80;
195       key_buf[6]=  (cid        & 0x3f) | 0x80;
196       key_buf[7] = '\0';
197     }
198   return
199     chise_get_attribute_table (db, key_buf, valdatum);
200 }
201
202
203 int
204 chise_open_attribute_table (CHISE_Attribute_Table **db,
205                             const char *db_dir,
206                             const char *encoding, const char *feature,
207                             DBTYPE real_subtype,
208                             u_int32_t accessmask, int modemask)
209 {
210   DB* dbase;
211   int status;
212   int len;
213   int size;
214   char *db_file_name;
215
216   status = db_create (&dbase, NULL, 0);
217   if (status)
218     return -1;
219
220   len = strlen (db_dir);
221   size = len + strlen (encoding) + strlen (feature) + 4;
222   db_file_name = alloca (size);
223   strcpy (db_file_name, db_dir);
224   if (db_file_name[len - 1] != '/')
225     {
226       db_file_name[len++] = '/';
227       db_file_name[len] = '\0';
228     }
229   strcat (db_file_name, encoding);
230   strcat (db_file_name, "/");
231   strcat (db_file_name, feature);
232   status = dbase->open (dbase, db_file_name, NULL,
233                         real_subtype, accessmask, modemask);
234   if (status)
235     {
236       dbase->close (dbase, 0);
237       return -1;
238     }
239   *db = dbase;
240   return 0;
241 }
242
243 int
244 chise_close_attribute_table (CHISE_Attribute_Table *db)
245 {
246   if (db)
247     {
248       db->sync  (db, 0);
249       db->close (db, 0);
250     }
251   return 0;
252 }
253
254 int
255 chise_get_attribute_table (CHISE_Attribute_Table *db,
256                            char *key, CHISE_Value *valdatum)
257 {
258   DBT keydatum;
259   int status = 0;
260
261   /* DB Version 2 requires DBT's to be zeroed before use. */
262   xzero (keydatum);
263   xzero (*valdatum);
264
265   keydatum.data = key;
266   keydatum.size = strlen (key);
267
268   status = db->get (db, NULL, &keydatum, valdatum, 0);
269   return status;
270 }