Include "cos-print.h".
[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 size_t
185 cos_string_size (COS_String string)
186 {
187   return string->size;
188 }
189
190 char*
191 cos_string_data (COS_String string)
192 {
193   return (char*)string->data;
194 }
195
196
197 int
198 cos_release_container (COS_Object obj)
199 {
200   return 0;
201 }
202
203
204 int
205 cos_release_sexp (COS_Object obj)
206 {
207   return 0;
208 }
209
210
211 int
212 cos_release_binary (COS_Object obj)
213 {
214   return 0;
215 }
216
217
218 COS_DS
219 concord_open_env (COS_object ds)
220 {
221   if (COS_OBJECT_DS_P (ds))
222     concord_current_env = (COS_DS)ds;
223   else
224     {
225       char* path;
226
227       if (COS_OBJECT_C_STRING_P (ds))
228         path = (char*)ds;
229       else if (ds == NULL)
230         path = CONCORD_SI_DB_DIR;
231       else
232         return NULL;
233
234       concord_current_env = concord_open_ds (CONCORD_Backend_Berkeley_DB,
235                                              path, 0, 0755);
236     }
237   return concord_current_env;
238 }
239
240 int
241 cos_release_ds (COS_Object obj)
242 {
243   return concord_close_ds ((COS_DS)obj);
244 }
245
246
247 COS_Genre
248 concord_get_genre (COS_object ds, COS_object genre)
249 {
250   if (COS_OBJECT_C_STRING_P (genre))
251     return concord_ds_get_genre (ds, (char*)genre);
252   else if (COS_OBJECT_SYMBOL_P (genre))
253     return concord_ds_get_genre (ds, (char*)((COS_Symbol)genre)->name->data);
254   else if (COS_OBJECT_GENRE_P (genre))
255     return (COS_Genre)genre;
256   return NULL;
257 }
258
259 int
260 cos_release_genre (COS_Object obj)
261 {
262   return concord_close_genre ((COS_Genre)obj);
263 }
264
265
266 COS_Feature
267 concord_get_feature (COS_object ds,
268                      COS_object genre, COS_object feature)
269 {
270   if (COS_OBJECT_FEATURE_P (feature))
271     return feature;
272   else
273     {
274       COS_Genre gobj = concord_get_genre (ds, genre);
275       char* feature_name;
276
277       if (COS_OBJECT_C_STRING_P (feature))
278         feature_name = (char*)feature;
279       else if (COS_OBJECT_STRING_P (feature))
280         feature_name = (char*)((COS_String)feature)->data;
281       else if (COS_OBJECT_SYMBOL_P (feature))
282         feature_name = (char*)((COS_Symbol)feature)->name->data;
283       else
284         return NULL;
285
286       return concord_genre_get_feature (gobj, feature_name);
287     }
288 }
289
290 int
291 cos_release_feature (COS_Object obj)
292 {
293   return concord_close_feature ((COS_Feature)obj);
294 }
295
296
297 COS_Feature_INDEX
298 concord_get_feature_index (COS_object ds,
299                            COS_object genre, COS_object feature)
300 {
301   if (COS_OBJECT_FEATURE_INDEX_P (feature))
302     return feature;
303   else
304     {
305       COS_Feature fobj = concord_get_feature (ds, genre, feature);
306       COS_Genre gobj;
307       char* feature_name;
308
309       if (fobj == NULL)
310         return NULL;
311
312       gobj = concord_feature_get_genre (fobj);
313       feature_name = concord_feature_get_name (fobj);
314       return concord_genre_get_index (gobj, feature_name);
315     }
316 }
317
318 int
319 cos_release_index (COS_Object obj)
320 {
321   return concord_close_index ((COS_Feature_INDEX)obj);
322 }
323
324
325 int
326 cos_release_db_object (COS_Object obj)
327 {
328   return 0;
329 }
330
331 COS_object
332 concord_decode_object (COS_object ds, COS_object genre,
333                        COS_object feature, COS_object id)
334 {
335   COS_Feature_INDEX index = concord_get_feature_index (ds, genre, feature);
336   char* id_str;
337   char buf[256];
338   CONCORD_String_Tank obj_st;
339   COS_String obj_string;
340   int cid;
341   size_t end;
342
343   if (index == NULL)
344     return NULL;
345
346   printf ("decoding id (%lX)...", id);
347   if (COS_OBJECT_INT_P (id))
348     {
349       printf ("(id is an int)...");
350       snprintf(buf, 256, "%ld", cos_int_value (id));
351       id_str = buf;
352     }
353   else if (COS_OBJECT_CHAR_P (id))
354     {
355       printf ("(id is a char)...");
356       snprintf(buf, 256, "%ld", cos_char_id (id));
357       id_str = buf;
358     }
359   else if (COS_OBJECT_SYMBOL_P (id))
360     {
361       printf ("(id is a symbol)....");
362       id_str = cos_string_data (cos_symbol_name ((COS_Symbol)id));
363     }
364   else if (COS_OBJECT_C_STRING_P (id))
365     {
366       printf ("(id is a C-string)....");
367       id_str = (char*)id;
368     }
369   else if (COS_OBJECT_STRING_P (id))
370     {
371       printf ("(id is a string)....");
372       id_str = cos_string_data ((COS_String)id);
373     }
374   else
375     return NULL;
376   printf ("done (%s).\n", id_str);
377
378   if ( concord_index_strid_get_obj_string (index, id_str, &obj_st) )
379     return NULL;
380
381   obj_string = cos_make_string ((char*)CONCORD_String_data (&obj_st),
382                                 CONCORD_String_size (&obj_st));
383
384   cid = cos_read_char (CONCORD_String_data (&obj_st),
385                        CONCORD_String_size (&obj_st),
386                        0, &end);
387   if ( cid >= 0 )
388     {
389       printf ("obj = %s (%d, U+%04X), len = %d, end = %d\n",
390               cos_string_data (obj_string),
391               cid, cid,
392               CONCORD_String_size (&obj_st), end);
393       cos_release_object (obj_string);
394       return cos_make_char (cid);
395     }
396   else
397     printf ("obj = %s\n", cos_string_data (obj_string));
398
399   cos_release_object (obj_string);
400
401   return NULL;
402 }
403
404 COS_object
405 concord_object_get_feature_value (COS_object object, COS_object feature)
406 {
407   char id_buf[256];
408   CONCORD_Feature fobj;
409   CONCORD_String_Tank val_st;
410   COS_String val_string;
411
412   if (COS_OBJECT_CHAR_P (object))
413     {
414       cos_utf8_print_char (object, id_buf, 256);
415       printf ("Object[char:0x%lX]'s id is %s.\n", object, id_buf);
416     }
417   else
418     return NULL;
419
420   fobj = concord_get_feature (concord_current_env,
421                               "character", feature);
422   if (fobj == NULL)
423     return NULL;
424
425   if ( concord_obj_get_feature_value_string (id_buf, fobj, &val_st) )
426     return NULL;
427
428   val_string = cos_make_string ((char*)CONCORD_String_data (&val_st),
429                                 CONCORD_String_size (&val_st));
430   printf ("obj[%s]'s %s = %s\n",
431           id_buf,
432           concord_feature_get_name (fobj),
433           cos_string_data (val_string));
434
435   return NULL;
436 }