1 /* Copyright (C) 2003,2004,2005,2006,2011 MORIOKA Tomohiko
2 This file is part of the CONCORD Library.
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.
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.
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
20 #include <sys/types.h>
27 #include "concord-name.h"
28 #include "concord-bdb.h"
32 CONCORD_String_size (const CONCORD_String s)
38 CONCORD_String_data (const CONCORD_String s)
43 CONCORD_Genre concord_ds_open_genre (CONCORD_DS ds, const char* name);
47 concord_genre_open_feature (CONCORD_Genre genre, const char* name);
51 concord_genre_open_index (CONCORD_Genre genre, const char* index);
54 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name);
58 concord_default_read_object (const unsigned char* string, size_t length);
63 COS_Object_Header header;
64 CONCORD_Backend_Type type;
66 CONCORD_NAME_TABLE* genre_names;
70 CONCORD_Object object_nil;
71 CONCORD_Object (*read_object) (const unsigned char* str, size_t length);
72 CONCORD_NAME_TABLE* symbol_names;
76 concord_default_read_object (const unsigned char* str, size_t length)
78 unsigned char* buf = malloc (length + 1);
82 strncpy ((char*)buf, (char*)str, length);
84 return (CONCORD_Object)buf;
88 concord_open_ds (CONCORD_Backend_Type type, const char* location,
89 int subtype, int modemask)
92 CONCORD_DS ds = (CONCORD_DS)malloc (sizeof (CONCORD_DS_ent));
93 size_t len = strlen (location);
98 ds->header.prefix = 0xff;
99 ds->header.type = CONCORD_Object_Type_DS;
101 CONCORD_DS ds = COS_ALLOCATE_OBJECT (DS);
102 size_t len = strlen (location);
109 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
110 ds->modemask = modemask;
111 ds->location = (char*)malloc (len + 1);
112 if (ds->location == NULL)
113 goto location_failure;
115 strcpy (ds->location, location);
117 ds->genre_names = concord_make_name_table ();
118 if (ds->genre_names == NULL)
126 ds->symbol_names = concord_make_name_table ();
127 if (ds->symbol_names == NULL)
129 concord_destroy_name_table (ds->genre_names);
135 ds->object_nil = NULL;
136 ds->read_object = &concord_default_read_object;
142 concord_close_ds (CONCORD_DS ds)
144 if (ds->location != NULL)
146 if (ds->genre_names != NULL)
147 concord_destroy_name_table (ds->genre_names);
148 if (ds->symbol_names != NULL)
149 concord_destroy_name_table (ds->symbol_names);
155 concord_ds_location (CONCORD_DS ds)
161 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
163 ds->object_nil = object_nil;
168 concord_ds_set_read_object_function (CONCORD_DS ds,
169 CONCORD_Object (*read_object)
170 (const unsigned char* str,
173 ds->read_object = read_object;
178 concord_ds_get_genre (CONCORD_DS ds, const char* name)
182 genre = concord_name_table_get (ds->genre_names, name);
186 genre = concord_ds_open_genre (ds, name);
190 if (concord_name_table_put (ds->genre_names, name, genre))
192 concord_close_genre (genre);
199 concord_ds_foreach_genre_name (CONCORD_DS ds,
200 int (*func) (CONCORD_DS ds, char* name))
202 char* dname = ds->location;
206 if ( (dir = opendir (dname)) == NULL)
209 while ( (de = readdir (dir)) != NULL )
211 if ( (strcmp (de->d_name, ".") != 0) &&
212 (strcmp (de->d_name, "..") != 0) )
214 int i, need_to_decode = 0;
219 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
230 name = (char*) alloca (i);
231 cp = (unsigned char*)de->d_name;
232 np = (unsigned char*)name;
234 while ( (ch = *cp++) != '\0')
250 if ( ('0' <= ch) && (ch <= '9') )
251 hex[index++] = ch - '0';
252 else if ( ('A' <= ch) && (ch <= 'F') )
253 hex[index++] = ch - 'A' + 10;
254 else if ( ('a' <= ch) && (ch <= 'f') )
255 hex[index++] = ch - 'a' + 10;
267 *np++ = (hex[0] << 4) | hex[1];
281 return closedir (dir);
284 return closedir (dir);
290 COS_Object_Header header;
293 CONCORD_NAME_TABLE* feature_names;
294 CONCORD_NAME_TABLE* index_names;
298 concord_ds_open_genre (CONCORD_DS ds, const char* name)
301 size_t len = strlen (name);
307 genre = (CONCORD_Genre)malloc (sizeof (CONCORD_Genre_ent));
311 genre->header.prefix = 0xff;
312 genre->header.type = CONCORD_Object_Type_Genre;
314 genre = COS_ALLOCATE_OBJECT (Genre);
320 genre->name = (char*)malloc (len + 1);
321 if (genre->name == NULL)
326 strcpy (genre->name, name);
328 genre->feature_names = concord_make_name_table ();
329 if (genre->feature_names == NULL)
336 genre->index_names = concord_make_name_table ();
337 if (genre->index_names == NULL)
339 free (genre->feature_names);
348 concord_close_genre (CONCORD_Genre genre)
355 if (genre->name == NULL)
363 if (genre->feature_names != NULL)
364 concord_destroy_name_table (genre->feature_names);
366 if (genre->index_names != NULL)
367 concord_destroy_name_table (genre->index_names);
374 concord_genre_get_name (CONCORD_Genre genre)
380 concord_genre_get_data_source (CONCORD_Genre genre)
386 concord_genre_foreach_feature_name (CONCORD_Genre genre,
387 int (*func) (CONCORD_Genre genre,
391 = alloca (strlen (genre->ds->location)
392 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
396 strcpy (dname, genre->ds->location);
398 strcat (dname, genre->name);
399 strcat (dname, "/feature");
401 if ( (dir = opendir (dname)) == NULL)
404 while ( (de = readdir (dir)) != NULL )
406 if ( (strcmp (de->d_name, ".") != 0) &&
407 (strcmp (de->d_name, "..") != 0) )
409 int i, need_to_decode = 0;
414 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
425 name = (char*) alloca (i);
426 cp = (unsigned char*)de->d_name;
427 np = (unsigned char*)name;
429 while ( (ch = *cp++) != '\0')
445 if ( ('0' <= ch) && (ch <= '9') )
446 hex[index++] = ch - '0';
447 else if ( ('A' <= ch) && (ch <= 'F') )
448 hex[index++] = ch - 'A' + 10;
449 else if ( ('a' <= ch) && (ch <= 'f') )
450 hex[index++] = ch - 'a' + 10;
462 *np++ = (hex[0] << 4) | hex[1];
475 if (func (genre, name))
476 return closedir (dir);
479 return closedir (dir);
483 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name)
485 CONCORD_Feature feature;
487 feature = concord_name_table_get (genre->feature_names, name);
491 feature = concord_genre_open_feature (genre, name);
495 if (concord_name_table_put (genre->feature_names, name, feature))
497 concord_close_feature (feature);
504 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
506 CONCORD_Genre g_feature
507 = concord_ds_get_genre (genre->ds, "feature");
509 if (g_feature != NULL)
511 CONCORD_Feature p_true_name
512 = concord_genre_get_feature_0 (g_feature, "true-name");
514 if (g_feature != NULL)
516 CONCORD_String_Tank s_true_name;
518 = concord_obj_get_feature_value_string (name,
523 char* t_name = alloca (s_true_name.size + 1);
525 strncpy (t_name, s_true_name.data, s_true_name.size);
526 t_name[s_true_name.size] = '\0';
527 return concord_genre_get_feature_0 (genre, t_name);
531 return concord_genre_get_feature_0 (genre, name);
535 concord_genre_get_index (CONCORD_Genre genre, const char* name)
539 index = concord_name_table_get (genre->index_names, name);
543 index = concord_genre_open_index (genre, name);
547 if (concord_name_table_put (genre->index_names, name, index))
549 concord_close_index (index);
556 struct COS_Feature_ent
558 COS_Object_Header header;
566 concord_genre_open_feature (CONCORD_Genre genre, const char* feature)
568 CONCORD_Feature table;
569 size_t len = strlen (feature);
575 table = (CONCORD_Feature)malloc (sizeof (CONCORD_Feature_ent));
579 table->header.prefix = 0xff;
580 table->header.type = CONCORD_Object_Type_Feature;
582 table = COS_ALLOCATE_OBJECT (Feature);
587 table->genre = genre;
590 table->name = (char*)malloc (len + 1);
591 if (table->name == NULL)
596 strcpy (table->name, feature);
601 concord_close_feature (CONCORD_Feature feature)
608 if (feature->db == NULL)
611 status = CONCORD_BDB_close (feature->db);
613 if (feature->name == NULL)
617 free (feature->name);
625 concord_feature_get_name (CONCORD_Feature feature)
627 return feature->name;
631 concord_feature_get_genre (CONCORD_Feature feature)
633 return feature->genre;
637 concord_feature_setup_db (CONCORD_Feature feature, int writable)
646 if ((feature->access & DB_CREATE) == 0)
648 if (feature->db != NULL)
650 CONCORD_BDB_close (feature->db);
660 if (feature->db == NULL)
662 CONCORD_Genre genre = feature->genre;
665 = CONCORD_BDB_open (genre->ds->location, genre->name,
666 "feature", feature->name,
668 access, genre->ds->modemask);
669 if (feature->db == NULL)
671 feature->access = access;
677 concord_feature_sync (CONCORD_Feature feature)
681 if (feature->db == NULL)
684 status = CONCORD_BDB_close (feature->db);
691 concord_obj_put_feature_value_str (const char* object_id,
692 CONCORD_Feature feature,
693 unsigned char* value)
697 if (concord_feature_setup_db (feature, 1))
699 return CONCORD_BDB_put (feature->db, object_id, value);
703 concord_obj_get_feature_value_string (const char* object_id,
704 CONCORD_Feature feature,
705 CONCORD_String value)
709 if (concord_feature_setup_db (feature, 0))
711 status = CONCORD_BDB_get (feature->db, object_id, value);
716 concord_obj_get_feature_value (const char* object_id,
717 CONCORD_Feature feature)
722 if (concord_feature_setup_db (feature, 0))
723 return feature->genre->ds->object_nil;
724 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
726 return feature->genre->ds->object_nil;
727 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
731 concord_obj_gets_feature_value (const char* object_id,
732 CONCORD_Feature feature,
733 unsigned char* dst, size_t size)
738 if (concord_feature_setup_db (feature, 0))
740 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
743 if (size < valdatum.size)
745 strncpy ((char*)dst, valdatum.data, valdatum.size);
746 dst[valdatum.size] = '\0';
751 concord_feature_foreach_obj_string (CONCORD_Feature feature,
752 int (*func)(CONCORD_String object_id,
753 CONCORD_Feature feature,
754 CONCORD_String value))
756 CONCORD_String_Tank key, value;
760 if (concord_feature_setup_db (feature, 0))
765 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
766 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
768 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
770 int ret = func (&key, feature, &value);
775 dbcp->c_close (dbcp);
780 struct COS_Feature_INDEX_ent
782 COS_Object_Header header;
790 concord_genre_open_index (CONCORD_Genre genre, const char* index)
793 size_t len = strlen (index);
799 table = (CONCORD_INDEX)malloc (sizeof (CONCORD_INDEX_ent));
803 table->header.prefix = 0xff;
804 table->header.type = CONCORD_Object_Type_INDEX;
806 table = COS_ALLOCATE_OBJECT (Feature_INDEX);
811 table->genre = genre;
814 table->name = (char*)malloc (len + 1);
815 if (table->name == NULL)
820 strcpy (table->name, index);
825 concord_close_index (CONCORD_INDEX table)
832 if (table->db == NULL)
835 status = CONCORD_BDB_close (table->db);
837 if (table->name == NULL)
849 concord_index_get_name (CONCORD_INDEX index)
855 concord_index_get_genre (CONCORD_INDEX index)
861 concord_index_setup_db (CONCORD_INDEX index, int writable)
870 if ((index->access & DB_CREATE) == 0)
872 if (index->db != NULL)
874 CONCORD_BDB_close (index->db);
884 if (index->db == NULL)
886 CONCORD_Genre genre = index->genre;
889 = CONCORD_BDB_open (genre->ds->location, genre->name,
890 "index", index->name,
892 access, genre->ds->modemask);
893 if (index->db == NULL)
895 index->access = access;
901 concord_index_sync (CONCORD_INDEX index)
905 if (index->db == NULL)
908 status = CONCORD_BDB_close (index->db);
915 concord_index_strid_put_obj (CONCORD_INDEX index,
916 const char* strid, char* object_id)
921 if (concord_index_setup_db (index, 1))
924 return CONCORD_BDB_put (index->db, strid, (unsigned char*)object_id);
928 concord_index_strid_get_obj_string (CONCORD_INDEX index,
930 CONCORD_String object_id)
935 if (concord_index_setup_db (index, 0))
938 return CONCORD_BDB_get (index->db, strid, object_id);