1 /* Copyright (C) 2003,2004,2005 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>
29 #include "concord-name.h"
30 #include "concord-bdb.h"
34 CONCORD_String_size (const CONCORD_String s)
40 CONCORD_String_data (const CONCORD_String s)
46 concord_ds_open_genre (CONCORD_DS ds, const unsigned char* name);
48 int concord_close_genre (CONCORD_Genre genre);
52 concord_genre_open_feature (CONCORD_Genre genre, const unsigned char* name);
54 int concord_close_feature (CONCORD_Feature feature);
58 concord_genre_open_index (CONCORD_Genre genre, const unsigned char* index);
61 concord_genre_get_feature_0 (CONCORD_Genre genre, const unsigned char* name);
63 int concord_close_index (CONCORD_INDEX table);
67 concord_default_read_object (const unsigned char* string, size_t length);
70 struct CONCORD_DS_Table
72 CONCORD_Backend_Type type;
73 unsigned char *location;
74 CONCORD_NAME_TABLE* genre_names;
78 CONCORD_Object object_nil;
79 CONCORD_Object (*read_object) (const unsigned char* str, size_t length);
83 concord_default_read_object (const unsigned char* str, size_t length)
85 unsigned char* buf = malloc (length + 1);
89 strncpy (buf, str, length);
95 concord_open_ds (CONCORD_Backend_Type type, const unsigned char* location,
96 int subtype, int modemask)
98 CONCORD_DS ds = (CONCORD_DS)malloc (sizeof (CONCORD_DS_Table));
99 size_t len = strlen (location);
105 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
106 ds->modemask = modemask;
107 ds->location = (unsigned char*)malloc (len + 1);
108 if (ds->location == NULL)
109 goto location_failure;
111 strcpy (ds->location, location);
113 ds->genre_names = concord_make_name_table ();
114 if (ds->genre_names == NULL)
122 ds->object_nil = NULL;
123 ds->read_object = &concord_default_read_object;
129 concord_close_ds (CONCORD_DS ds)
131 if (ds->location != NULL)
133 if (ds->genre_names != NULL)
134 concord_destroy_name_table (ds->genre_names);
140 concord_ds_location (CONCORD_DS ds)
146 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
148 ds->object_nil = object_nil;
153 concord_ds_set_read_object_function (CONCORD_DS ds,
154 CONCORD_Object (*read_object)
155 (const unsigned char* str,
158 ds->read_object = read_object;
163 concord_ds_get_genre (CONCORD_DS ds, const unsigned char* name)
167 genre = concord_name_table_get (ds->genre_names, name);
171 genre = concord_ds_open_genre (ds, name);
175 if (concord_name_table_put (ds->genre_names, name, genre))
177 concord_close_genre (genre);
184 concord_ds_foreach_genre_name (CONCORD_DS ds,
185 int (*func) (CONCORD_DS ds,
186 unsigned char* name))
188 unsigned char* dname = ds->location;
192 if ( (dir = opendir (dname)) == NULL)
195 while ( (de = readdir (dir)) != NULL )
197 if ( (strcmp (de->d_name, ".") != 0) &&
198 (strcmp (de->d_name, "..") != 0) )
200 int i, need_to_decode = 0;
205 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
216 name = (unsigned char *) alloca (i);
220 while ( (ch = *cp++) != '\0')
236 if ( ('0' <= ch) && (ch <= '9') )
237 hex[index++] = ch - '0';
238 else if ( ('A' <= ch) && (ch <= 'F') )
239 hex[index++] = ch - 'A' + 10;
240 else if ( ('a' <= ch) && (ch <= 'f') )
241 hex[index++] = ch - 'a' + 10;
253 *np++ = (hex[0] << 4) | hex[1];
267 return closedir (dir);
270 return closedir (dir);
274 struct CONCORD_Genre_Table
278 CONCORD_NAME_TABLE* feature_names;
279 CONCORD_NAME_TABLE* index_names;
283 concord_ds_open_genre (CONCORD_DS ds, const unsigned char* name)
286 size_t len = strlen (name);
291 genre = (CONCORD_Genre)malloc (sizeof (CONCORD_Genre_Table));
296 genre->name = (unsigned char*)malloc (len + 1);
297 if (genre->name == NULL)
302 strcpy (genre->name, name);
304 genre->feature_names = concord_make_name_table ();
305 if (genre->feature_names == NULL)
312 genre->index_names = concord_make_name_table ();
313 if (genre->index_names == NULL)
315 free (genre->feature_names);
324 concord_close_genre (CONCORD_Genre genre)
331 if (genre->name == NULL)
339 if (genre->feature_names != NULL)
340 concord_destroy_name_table (genre->feature_names);
342 if (genre->index_names != NULL)
343 concord_destroy_name_table (genre->index_names);
350 concord_genre_get_name (CONCORD_Genre genre)
356 concord_genre_get_data_source (CONCORD_Genre genre)
362 concord_genre_foreach_feature_name (CONCORD_Genre genre,
363 int (*func) (CONCORD_Genre genre,
364 unsigned char* name))
367 = alloca (strlen (genre->ds->location)
368 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
372 strcpy (dname, genre->ds->location);
374 strcat (dname, genre->name);
375 strcat (dname, "/feature");
377 if ( (dir = opendir (dname)) == NULL)
380 while ( (de = readdir (dir)) != NULL )
382 if ( (strcmp (de->d_name, ".") != 0) &&
383 (strcmp (de->d_name, "..") != 0) )
385 int i, need_to_decode = 0;
390 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
401 name = (unsigned char *) alloca (i);
405 while ( (ch = *cp++) != '\0')
421 if ( ('0' <= ch) && (ch <= '9') )
422 hex[index++] = ch - '0';
423 else if ( ('A' <= ch) && (ch <= 'F') )
424 hex[index++] = ch - 'A' + 10;
425 else if ( ('a' <= ch) && (ch <= 'f') )
426 hex[index++] = ch - 'a' + 10;
438 *np++ = (hex[0] << 4) | hex[1];
451 if (func (genre, name))
452 return closedir (dir);
455 return closedir (dir);
459 concord_genre_get_feature_0 (CONCORD_Genre genre, const unsigned char* name)
461 CONCORD_Feature feature;
463 feature = concord_name_table_get (genre->feature_names, name);
467 feature = concord_genre_open_feature (genre, name);
471 if (concord_name_table_put (genre->feature_names, name, feature))
473 concord_close_feature (feature);
480 concord_genre_get_feature (CONCORD_Genre genre, const unsigned char* name)
482 CONCORD_Genre g_feature
483 = concord_ds_get_genre (genre->ds, "feature");
485 if (g_feature != NULL)
487 CONCORD_Feature p_true_name
488 = concord_genre_get_feature_0 (g_feature, "true-name");
490 if (g_feature != NULL)
492 CONCORD_String_Tank s_true_name;
494 = concord_obj_get_feature_value_string (name,
499 unsigned char* t_name = alloca (s_true_name.size + 1);
501 strncpy (t_name, s_true_name.data, s_true_name.size);
502 t_name[s_true_name.size] = '\0';
503 return concord_genre_get_feature_0 (genre, t_name);
507 return concord_genre_get_feature_0 (genre, name);
511 concord_genre_get_index (CONCORD_Genre genre, const unsigned char* name)
515 index = concord_name_table_get (genre->index_names, name);
519 index = concord_genre_open_index (genre, name);
523 if (concord_name_table_put (genre->index_names, name, index))
525 concord_close_index (index);
532 struct CONCORD_Feature_Table
541 concord_genre_open_feature (CONCORD_Genre genre, const unsigned char* feature)
543 CONCORD_Feature table;
544 size_t len = strlen (feature);
549 table = (CONCORD_Feature)malloc (sizeof (CONCORD_Feature_Table));
553 table->genre = genre;
556 table->name = (unsigned char*)malloc (len + 1);
557 if (table->name == NULL)
562 strcpy (table->name, feature);
567 concord_close_feature (CONCORD_Feature feature)
574 if (feature->db == NULL)
577 status = CONCORD_BDB_close (feature->db);
579 if (feature->name == NULL)
583 free (feature->name);
591 concord_feature_get_name (CONCORD_Feature feature)
593 return feature->name;
597 concord_feature_get_genre (CONCORD_Feature feature)
599 return feature->genre;
603 concord_feature_setup_db (CONCORD_Feature feature, int writable)
612 if ((feature->access & DB_CREATE) == 0)
614 if (feature->db != NULL)
616 CONCORD_BDB_close (feature->db);
626 if (feature->db == NULL)
628 CONCORD_Genre genre = feature->genre;
631 = CONCORD_BDB_open (genre->ds->location, genre->name,
632 "feature", feature->name,
634 access, genre->ds->modemask);
635 if (feature->db == NULL)
637 feature->access = access;
643 concord_feature_sync (CONCORD_Feature feature)
647 if (feature->db == NULL)
650 status = CONCORD_BDB_close (feature->db);
657 concord_obj_put_feature_value_str (const unsigned char* object_id,
658 CONCORD_Feature feature,
659 unsigned char* value)
663 if (concord_feature_setup_db (feature, 1))
665 return CONCORD_BDB_put (feature->db, object_id, value);
669 concord_obj_get_feature_value_string (const unsigned char* object_id,
670 CONCORD_Feature feature,
671 CONCORD_String value)
675 if (concord_feature_setup_db (feature, 0))
677 status = CONCORD_BDB_get (feature->db, object_id, value);
682 concord_obj_get_feature_value (const unsigned char* object_id,
683 CONCORD_Feature feature)
688 if (concord_feature_setup_db (feature, 0))
689 return feature->genre->ds->object_nil;
690 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
692 return feature->genre->ds->object_nil;
693 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
697 concord_obj_gets_feature_value (const unsigned char* object_id,
698 CONCORD_Feature feature,
699 unsigned char* dst, size_t size)
704 if (concord_feature_setup_db (feature, 0))
706 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
709 if (size < valdatum.size)
711 strncpy (dst, valdatum.data, valdatum.size);
712 dst[valdatum.size] = '\0';
717 concord_feature_foreach_obj_string (CONCORD_Feature feature,
718 int (*func)(CONCORD_String object_id,
719 CONCORD_Feature feature,
720 CONCORD_String value))
722 CONCORD_String_Tank key, value;
726 if (concord_feature_setup_db (feature, 0))
731 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
732 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
734 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
736 int ret = func (&key, feature, &value);
741 dbcp->c_close (dbcp);
746 struct CONCORD_INDEX_Table
755 concord_genre_open_index (CONCORD_Genre genre, const unsigned char* index)
758 size_t len = strlen (index);
763 table = (CONCORD_INDEX)malloc (sizeof (CONCORD_INDEX_Table));
767 table->genre = genre;
770 table->name = (unsigned char*)malloc (len + 1);
771 if (table->name == NULL)
776 strcpy (table->name, index);
781 concord_close_index (CONCORD_INDEX table)
788 if (table->db == NULL)
791 status = CONCORD_BDB_close (table->db);
793 if (table->name == NULL)
805 concord_index_setup_db (CONCORD_INDEX index, int writable)
814 if ((index->access & DB_CREATE) == 0)
816 if (index->db != NULL)
818 CONCORD_BDB_close (index->db);
828 if (index->db == NULL)
830 CONCORD_Genre genre = index->genre;
833 = CONCORD_BDB_open (genre->ds->location, genre->name,
834 "index", index->name,
836 access, genre->ds->modemask);
837 if (index->db == NULL)
839 index->access = access;
845 concord_index_sync (CONCORD_INDEX index)
849 if (index->db == NULL)
852 status = CONCORD_BDB_close (index->db);
859 concord_index_strid_put_obj (CONCORD_INDEX index,
860 const unsigned char* strid,
861 unsigned char* object_id)
866 if (concord_index_setup_db (index, 1))
869 return CONCORD_BDB_put (index->db, strid, object_id);
873 concord_index_strid_get_obj_string (CONCORD_INDEX index,
874 const unsigned char* strid,
875 CONCORD_String object_id)
880 if (concord_index_setup_db (index, 0))
883 return CONCORD_BDB_get (index->db, strid, object_id);