97f6099fe4f811c50b89b04d58452fa0478fce12
[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
24 const char concord_db_format_version[] = CONCORD_DB_FORMAT_VERSION;
25 const char concord_db_dir[] = CONCORD_DB_DIR;
26 const char concord_system_db_dir[] = CONCORD_SI_DB_DIR;
27
28 int (*COS_Object_release_function_table
29      [COS_OBJECT_TYPE_MAX - COS_Object_Type_char])
30   (COS_Object)
31   = { cos_release_string,
32       cos_release_symbol,
33       cos_release_container,
34       cos_release_sexp,
35       cos_release_binary,
36       cos_release_ds,
37       cos_release_genre,
38       cos_release_feature,
39       cos_release_index,
40       cos_release_db_object
41 };
42
43
44 COS_object
45 cos_make_int (COS_C_Int num)
46 {
47   return (COS_object)((COS_INT)(num << 1) | 1);
48 }
49
50 COS_C_Int
51 cos_int_value (COS_object obj)
52 {
53   if (COS_OBJECT_INT_P (obj))
54     return ((COS_INT)obj) >> 1;
55   return INTPTR_MIN;
56 }
57
58 int
59 cos_int_p (COS_object obj)
60 {
61   return COS_OBJECT_INT_P (obj);
62 }
63
64
65 COS_object
66 cos_make_char (int code)
67 {
68   return (COS_object)((COS_INT)(code << 2) | 2);
69 }
70
71 int
72 cos_char_id (COS_object obj)
73 {
74   if (COS_OBJECT_CHAR_P (obj))
75     return ((COS_INT)obj) >> 2;
76   return -1;
77 }
78
79 int
80 cos_char_p (COS_object obj)
81 {
82   return COS_OBJECT_CHAR_P (obj);
83 }
84
85
86 COS_Object
87 cos_allocate_object_0 (enum COS_Object_Type type, size_t size)
88 {
89   COS_Object obj = (COS_Object)malloc (size);
90
91   if (obj == NULL)
92     return NULL;
93
94   obj->header.prefix = COS_OBJECT_PREFIX_OBJECT;
95   obj->header.type = type;
96   obj->header.reference_count = 0;
97
98   return obj;
99 }
100
101 COS_Object
102 cos_retain_object (COS_Object obj)
103 {
104   obj->header.reference_count++;
105
106   return obj;
107 }
108
109 int
110 cos_release_object (COS_object obj)
111 {
112   ((COS_Object)obj)->header.reference_count--;
113
114   if ( ((COS_Object)obj)->header.reference_count <= 0 )
115     return (*COS_Object_release_function_table
116             [((COS_Object)obj)->header.type
117              - COS_FAT_OBJECT_TYPE_MIN])(obj);
118   else
119     return 0;
120 }
121
122
123 COS_String
124 cos_make_string (char* str, size_t size)
125 {
126   COS_String obj = COS_ALLOCATE_OBJECT (String);
127
128   if (obj == NULL)
129     return NULL;
130
131   obj->size = size;
132   obj->data = malloc (size + 1);
133   if (obj->data == NULL)
134     {
135       free (obj);
136       return NULL;
137     }
138
139   strncpy ((char*)obj->data, str, size);
140   obj->data[size] = '\0';
141   return obj;
142 }
143
144 COS_String
145 cos_build_string (char* str)
146 {
147 #if 0
148   COS_String obj = COS_ALLOCATE_OBJECT (string);
149
150   if (obj == NULL)
151     return NULL;
152
153   obj->size = strlen (str);
154   obj->data = malloc (obj->size + 1);
155   if (obj->data == NULL)
156     {
157       free (obj);
158       return NULL;
159     }
160
161   strncpy ((char*)obj->data, str, obj->size);
162   obj->data[obj->size] = '\0';
163   return obj;
164 #else
165   return cos_make_string (str, strlen (str));
166 #endif
167 }
168
169 int
170 cos_release_string (COS_Object obj)
171 {
172   if (obj == NULL)
173     return 0;
174
175   if ( ((COS_String)obj)->data != NULL)
176     free (((COS_String)obj)->data);
177   free (obj);
178   return 0;
179 }
180
181 size_t
182 cos_string_size (COS_String string)
183 {
184   return string->size;
185 }
186
187 char*
188 cos_string_data (COS_String string)
189 {
190   return (char*)string->data;
191 }
192
193
194 int
195 cos_release_container (COS_Object obj)
196 {
197   return 0;
198 }
199
200
201 int
202 cos_release_sexp (COS_Object obj)
203 {
204   return 0;
205 }
206
207
208 int
209 cos_release_binary (COS_Object obj)
210 {
211   return 0;
212 }
213
214
215 COS_DS
216 concord_open_env (COS_object ds)
217 {
218   if (COS_OBJECT_DS_P (ds))
219     return (COS_DS)ds;
220   else
221     {
222       char* path;
223
224       if (COS_OBJECT_C_STRING_P (ds))
225         path = (char*)ds;
226       else if (ds == NULL)
227         path = CONCORD_SI_DB_DIR;
228       else
229         return NULL;
230
231       return concord_open_ds (CONCORD_Backend_Berkeley_DB,
232                               path, 0, 0755);
233     }
234 }
235
236 int
237 cos_release_ds (COS_Object obj)
238 {
239   return concord_close_ds ((COS_DS)obj);
240 }
241
242
243 COS_Genre
244 concord_get_genre (COS_object ds, COS_object genre)
245 {
246   if (COS_OBJECT_C_STRING_P (genre))
247     return concord_ds_get_genre (ds, (char*)genre);
248   else if (COS_OBJECT_SYMBOL_P (genre))
249     return concord_ds_get_genre (ds, (char*)((COS_Symbol)genre)->name->data);
250   else if (COS_OBJECT_GENRE_P (genre))
251     return (COS_Genre)genre;
252   return NULL;
253 }
254
255 int
256 cos_release_genre (COS_Object obj)
257 {
258   return concord_close_genre ((COS_Genre)obj);
259 }
260
261
262 COS_Feature
263 concord_get_feature (COS_object ds,
264                      COS_object genre, COS_object feature)
265 {
266   if (COS_OBJECT_FEATURE_P (feature))
267     return feature;
268   else
269     {
270       COS_Genre gobj = concord_get_genre (ds, genre);
271       char* feature_name;
272
273       if (COS_OBJECT_C_STRING_P (feature))
274         feature_name = (char*)feature;
275       else if (COS_OBJECT_STRING_P (feature))
276         feature_name = (char*)((COS_String)feature)->data;
277       else if (COS_OBJECT_SYMBOL_P (feature))
278         feature_name = (char*)((COS_Symbol)feature)->name->data;
279       else
280         return NULL;
281
282       return concord_genre_get_feature (gobj, feature_name);
283     }
284 }
285
286 int
287 cos_release_feature (COS_Object obj)
288 {
289   return concord_close_feature ((COS_Feature)obj);
290 }
291
292
293 COS_Feature_INDEX
294 concord_get_feature_index (COS_object ds,
295                            COS_object genre, COS_object feature)
296 {
297   if (COS_OBJECT_FEATURE_INDEX_P (feature))
298     return feature;
299   else
300     {
301       COS_Feature fobj = concord_get_feature (ds, genre, feature);
302       COS_Genre gobj;
303       char* feature_name;
304
305       if (fobj == NULL)
306         return NULL;
307
308       gobj = concord_feature_get_genre (fobj);
309       feature_name = concord_feature_get_name (fobj);
310       return concord_genre_get_index (gobj, feature_name);
311     }
312 }
313
314 int
315 cos_release_index (COS_Object obj)
316 {
317   return concord_close_index ((COS_Feature_INDEX)obj);
318 }
319
320
321 int
322 cos_release_db_object (COS_Object obj)
323 {
324   return 0;
325 }
326
327 COS_object
328 concord_decode_object (COS_object ds, COS_object genre,
329                        COS_object feature, COS_object id)
330 {
331   COS_Feature_INDEX index = concord_get_feature_index (ds, genre, feature);
332   char* id_str;
333   char buf[256];
334   CONCORD_String_Tank obj_st;
335   COS_String obj_string;
336   int cid;
337   size_t end;
338
339   if (index == NULL)
340     return NULL;
341
342   printf ("decoding id (%lX)...", id);
343   if (COS_OBJECT_INT_P (id))
344     {
345       printf ("(id is an int)...");
346       snprintf(buf, 256, "%ld", cos_int_value (id));
347       id_str = buf;
348     }
349   else if (COS_OBJECT_CHAR_P (id))
350     {
351       printf ("(id is a char)...");
352       snprintf(buf, 256, "%ld", cos_char_id (id));
353       id_str = buf;
354     }
355   else if (COS_OBJECT_SYMBOL_P (id))
356     {
357       printf ("(id is a symbol)....");
358       id_str = cos_string_data (cos_symbol_name ((COS_Symbol)id));
359     }
360   else if (COS_OBJECT_C_STRING_P (id))
361     {
362       printf ("(id is a C-string)....");
363       id_str = (char*)id;
364     }
365   else if (COS_OBJECT_STRING_P (id))
366     {
367       printf ("(id is a string)....");
368       id_str = cos_string_data ((COS_String)id);
369     }
370   else
371     return NULL;
372   printf ("done (%s).\n", id_str);
373
374   if ( concord_index_strid_get_obj_string (index, id_str, &obj_st) )
375     return NULL;
376
377   obj_string = cos_make_string ((char*)CONCORD_String_data (&obj_st),
378                                 CONCORD_String_size (&obj_st));
379
380   cid = cos_read_char (CONCORD_String_data (&obj_st),
381                        CONCORD_String_size (&obj_st),
382                        0, &end);
383   if ( cid >= 0 )
384     {
385       printf ("obj = %s (%d, U+%04X), len = %d, end = %d\n",
386               cos_string_data (obj_string),
387               cid, cid,
388               CONCORD_String_size (&obj_st), end);
389       cos_release_object (obj_string);
390       return cos_make_char (cid);
391     }
392   else
393     printf ("obj = %s\n", cos_string_data (obj_string));
394
395   cos_release_object (obj_string);
396
397   return NULL;
398 }