(cos_read_int): New prototype.
[chise/concord.git] / cos.c
1 /* Copyright (C) 2013 MORIOKA Tomohiko
2    This file is part of the CONCORD Library.
3
4    The CONCORD Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The CONCORD Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the CONCORD Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <stdlib.h>
20 #include "sysdep.h"
21 #include "cos-i.h"
22 #include "cos-read.h"
23 #include "cos-print.h"
24
25 const char concord_db_format_version[] = CONCORD_DB_FORMAT_VERSION;
26 const char concord_db_dir[] = CONCORD_DB_DIR;
27 const char concord_system_db_dir[] = CONCORD_SI_DB_DIR;
28
29 CONCORD_DS concord_current_env = NULL;
30
31 int (*COS_Object_release_function_table
32      [COS_OBJECT_TYPE_MAX - COS_Object_Type_char])
33   (COS_Object)
34   = { cos_release_string,
35       cos_release_symbol,
36       cos_release_container,
37       cos_release_sexp,
38       cos_release_binary,
39       cos_release_ds,
40       cos_release_genre,
41       cos_release_feature,
42       cos_release_index,
43       cos_release_db_object
44 };
45
46
47 COS_object
48 cos_make_int (COS_C_Int num)
49 {
50   return (COS_object)((COS_INT)(num << 1) | 1);
51 }
52
53 COS_C_Int
54 cos_int_value (COS_object obj)
55 {
56   if (COS_OBJECT_INT_P (obj))
57     return ((COS_INT)obj) >> 1;
58   return INTPTR_MIN;
59 }
60
61 int
62 cos_int_p (COS_object obj)
63 {
64   return COS_OBJECT_INT_P (obj);
65 }
66
67
68 COS_object
69 cos_make_char (int code)
70 {
71   return (COS_object)((COS_INT)(code << 2) | 2);
72 }
73
74 int
75 cos_char_id (COS_object obj)
76 {
77   if (COS_OBJECT_CHAR_P (obj))
78     return ((COS_INT)obj) >> 2;
79   return -1;
80 }
81
82 int
83 cos_char_p (COS_object obj)
84 {
85   return COS_OBJECT_CHAR_P (obj);
86 }
87
88
89 COS_Object
90 cos_allocate_object_0 (enum COS_Object_Type type, size_t size)
91 {
92   COS_Object obj = (COS_Object)malloc (size);
93
94   if (obj == NULL)
95     return NULL;
96
97   obj->header.prefix = COS_OBJECT_PREFIX_OBJECT;
98   obj->header.type = type;
99   obj->header.reference_count = 0;
100
101   return obj;
102 }
103
104 COS_Object
105 cos_retain_object (COS_Object obj)
106 {
107   obj->header.reference_count++;
108
109   return obj;
110 }
111
112 int
113 cos_release_object (COS_object obj)
114 {
115   ((COS_Object)obj)->header.reference_count--;
116
117   if ( ((COS_Object)obj)->header.reference_count <= 0 )
118     return (*COS_Object_release_function_table
119             [((COS_Object)obj)->header.type
120              - COS_FAT_OBJECT_TYPE_MIN])(obj);
121   else
122     return 0;
123 }
124
125
126 COS_String
127 cos_make_string (char* str, size_t size)
128 {
129   COS_String obj = COS_ALLOCATE_OBJECT (String);
130
131   if (obj == NULL)
132     return NULL;
133
134   obj->size = size;
135   obj->data = malloc (size + 1);
136   if (obj->data == NULL)
137     {
138       free (obj);
139       return NULL;
140     }
141
142   strncpy ((char*)obj->data, str, size);
143   obj->data[size] = '\0';
144   return obj;
145 }
146
147 COS_String
148 cos_build_string (char* str)
149 {
150 #if 0
151   COS_String obj = COS_ALLOCATE_OBJECT (string);
152
153   if (obj == NULL)
154     return NULL;
155
156   obj->size = strlen (str);
157   obj->data = malloc (obj->size + 1);
158   if (obj->data == NULL)
159     {
160       free (obj);
161       return NULL;
162     }
163
164   strncpy ((char*)obj->data, str, obj->size);
165   obj->data[obj->size] = '\0';
166   return obj;
167 #else
168   return cos_make_string (str, strlen (str));
169 #endif
170 }
171
172 int
173 cos_release_string (COS_Object obj)
174 {
175   if (obj == NULL)
176     return 0;
177
178   if ( ((COS_String)obj)->data != NULL)
179     free (((COS_String)obj)->data);
180   free (obj);
181   return 0;
182 }
183
184 int cos_string_p (COS_object obj)
185 {
186   return COS_OBJECT_STRING_P (obj);
187 }
188
189 size_t
190 cos_string_size (COS_String string)
191 {
192   return string->size;
193 }
194
195 char*
196 cos_string_data (COS_String string)
197 {
198   return (char*)string->data;
199 }
200
201
202 int
203 cos_release_container (COS_Object obj)
204 {
205   return 0;
206 }
207
208
209 int
210 cos_release_sexp (COS_Object obj)
211 {
212   return 0;
213 }
214
215
216 int
217 cos_release_binary (COS_Object obj)
218 {
219   return 0;
220 }
221
222
223 COS_DS
224 concord_open_env (COS_object ds)
225 {
226   if (COS_OBJECT_DS_P (ds))
227     concord_current_env = (COS_DS)ds;
228   else
229     {
230       char* path;
231
232       if (COS_OBJECT_C_STRING_P (ds))
233         path = (char*)ds;
234       else if (ds == NULL)
235         path = CONCORD_SI_DB_DIR;
236       else
237         return NULL;
238
239       concord_current_env = concord_open_ds (CONCORD_Backend_Berkeley_DB,
240                                              path, 0, 0755);
241     }
242   return concord_current_env;
243 }
244
245 int
246 cos_release_ds (COS_Object obj)
247 {
248   return concord_close_ds ((COS_DS)obj);
249 }
250
251
252 COS_Genre
253 concord_get_genre (COS_object ds, COS_object genre)
254 {
255   if (COS_OBJECT_C_STRING_P (genre))
256     return concord_ds_get_genre (ds, (char*)genre);
257   else if (COS_OBJECT_SYMBOL_P (genre))
258     return concord_ds_get_genre (ds, (char*)((COS_Symbol)genre)->name->data);
259   else if (COS_OBJECT_GENRE_P (genre))
260     return (COS_Genre)genre;
261   return NULL;
262 }
263
264 int
265 cos_release_genre (COS_Object obj)
266 {
267   return concord_close_genre ((COS_Genre)obj);
268 }
269
270
271 COS_Feature
272 concord_get_feature (COS_object ds,
273                      COS_object genre, COS_object feature)
274 {
275   if (COS_OBJECT_FEATURE_P (feature))
276     return feature;
277   else
278     {
279       COS_Genre gobj = concord_get_genre (ds, genre);
280       char* feature_name;
281
282       if (COS_OBJECT_C_STRING_P (feature))
283         feature_name = (char*)feature;
284       else if (COS_OBJECT_STRING_P (feature))
285         feature_name = (char*)((COS_String)feature)->data;
286       else if (COS_OBJECT_SYMBOL_P (feature))
287         feature_name = (char*)((COS_Symbol)feature)->name->data;
288       else
289         return NULL;
290
291       return concord_genre_get_feature (gobj, feature_name);
292     }
293 }
294
295 int
296 cos_release_feature (COS_Object obj)
297 {
298   return concord_close_feature ((COS_Feature)obj);
299 }
300
301
302 COS_Feature_INDEX
303 concord_get_feature_index (COS_object ds,
304                            COS_object genre, COS_object feature)
305 {
306   if (COS_OBJECT_FEATURE_INDEX_P (feature))
307     return feature;
308   else
309     {
310       COS_Feature fobj = concord_get_feature (ds, genre, feature);
311       COS_Genre gobj;
312       char* feature_name;
313
314       if (fobj == NULL)
315         return NULL;
316
317       gobj = concord_feature_get_genre (fobj);
318       feature_name = concord_feature_get_name (fobj);
319       return concord_genre_get_index (gobj, feature_name);
320     }
321 }
322
323 int
324 cos_release_index (COS_Object obj)
325 {
326   return concord_close_index ((COS_Feature_INDEX)obj);
327 }
328
329
330 int
331 cos_release_db_object (COS_Object obj)
332 {
333   return 0;
334 }
335
336 COS_object
337 concord_decode_object (COS_object ds, COS_object genre,
338                        COS_object feature, COS_object id)
339 {
340   COS_Feature_INDEX index = concord_get_feature_index (ds, genre, feature);
341   char* id_str;
342   char buf[256];
343   CONCORD_String_Tank obj_st;
344   COS_String obj_string;
345   int cid;
346   size_t end;
347
348   if (index == NULL)
349     return NULL;
350
351   printf ("decoding id (%lX)...", id);
352   if (COS_OBJECT_INT_P (id))
353     {
354       printf ("(id is an int)...");
355       snprintf(buf, 256, "%ld", cos_int_value (id));
356       id_str = buf;
357     }
358   else if (COS_OBJECT_CHAR_P (id))
359     {
360       printf ("(id is a char)...");
361       snprintf(buf, 256, "%ld", cos_char_id (id));
362       id_str = buf;
363     }
364   else if (COS_OBJECT_SYMBOL_P (id))
365     {
366       printf ("(id is a symbol)....");
367       id_str = cos_string_data (cos_symbol_name ((COS_Symbol)id));
368     }
369   else if (COS_OBJECT_C_STRING_P (id))
370     {
371       printf ("(id is a C-string)....");
372       id_str = (char*)id;
373     }
374   else if (COS_OBJECT_STRING_P (id))
375     {
376       printf ("(id is a string)....");
377       id_str = cos_string_data ((COS_String)id);
378     }
379   else
380     return NULL;
381   printf ("done (%s).\n", id_str);
382
383   if ( concord_index_strid_get_obj_string (index, id_str, &obj_st) )
384     return NULL;
385
386   obj_string = cos_make_string ((char*)CONCORD_String_data (&obj_st),
387                                 CONCORD_String_size (&obj_st));
388
389   cid = cos_read_char (CONCORD_String_data (&obj_st),
390                        CONCORD_String_size (&obj_st),
391                        0, &end);
392   if ( cid >= 0 )
393     {
394       printf ("obj = %s (%d, U+%04X), len = %d, end = %d\n",
395               cos_string_data (obj_string),
396               cid, cid,
397               CONCORD_String_size (&obj_st), end);
398       cos_release_object (obj_string);
399       return cos_make_char (cid);
400     }
401   else
402     printf ("obj = %s\n", cos_string_data (obj_string));
403
404   cos_release_object (obj_string);
405
406   return NULL;
407 }
408
409 COS_object
410 concord_object_get_feature_value (COS_object object, COS_object feature)
411 {
412   char id_buf[256];
413   CONCORD_Feature fobj;
414   CONCORD_String_Tank val_st;
415   COS_String val_string;
416   size_t end;
417   int val_cid;
418   COS_String val_str;
419
420   if (COS_OBJECT_CHAR_P (object))
421     {
422       cos_utf8_print_char (object, id_buf, 256);
423       printf ("Object[char:0x%lX]'s id is %s.\n", object, id_buf);
424     }
425   else
426     return NULL;
427
428   fobj = concord_get_feature (concord_current_env,
429                               "character", feature);
430   if (fobj == NULL)
431     return NULL;
432
433   if ( concord_obj_get_feature_value_string (id_buf, fobj, &val_st) )
434     return NULL;
435
436   val_string = cos_make_string ((char*)CONCORD_String_data (&val_st),
437                                 CONCORD_String_size (&val_st));
438   printf ("obj[%s]'s %s = %s\n",
439           id_buf,
440           concord_feature_get_name (fobj),
441           cos_string_data (val_string));
442
443   val_cid = cos_read_char (CONCORD_String_data (&val_st),
444                            CONCORD_String_size (&val_st),
445                            0, &end);
446   if ( val_cid >= 0 )
447     return cos_make_char (val_cid);
448
449   val_str = cos_read_string (CONCORD_String_data (&val_st),
450                              CONCORD_String_size (&val_st),
451                              0, &end);
452   if ( val_str != NULL )
453     return val_str;
454
455   return NULL;
456 }