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_data_source (CONCORD_Genre genre)
356 concord_genre_foreach_feature_name (CONCORD_Genre genre,
357 int (*func) (CONCORD_Genre genre,
358 unsigned char* name))
361 = alloca (strlen (genre->ds->location)
362 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
366 strcpy (dname, genre->ds->location);
368 strcat (dname, genre->name);
369 strcat (dname, "/feature");
371 if ( (dir = opendir (dname)) == NULL)
374 while ( (de = readdir (dir)) != NULL )
376 if ( (strcmp (de->d_name, ".") != 0) &&
377 (strcmp (de->d_name, "..") != 0) )
379 int i, need_to_decode = 0;
384 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
395 name = (unsigned char *) alloca (i);
399 while ( (ch = *cp++) != '\0')
415 if ( ('0' <= ch) && (ch <= '9') )
416 hex[index++] = ch - '0';
417 else if ( ('A' <= ch) && (ch <= 'F') )
418 hex[index++] = ch - 'A' + 10;
419 else if ( ('a' <= ch) && (ch <= 'f') )
420 hex[index++] = ch - 'a' + 10;
432 *np++ = (hex[0] << 4) | hex[1];
445 if (func (genre, name))
446 return closedir (dir);
449 return closedir (dir);
453 concord_genre_get_feature_0 (CONCORD_Genre genre, const unsigned char* name)
455 CONCORD_Feature feature;
457 feature = concord_name_table_get (genre->feature_names, name);
461 feature = concord_genre_open_feature (genre, name);
465 if (concord_name_table_put (genre->feature_names, name, feature))
467 concord_close_feature (feature);
474 concord_genre_get_feature (CONCORD_Genre genre, const unsigned char* name)
476 CONCORD_Genre g_feature
477 = concord_ds_get_genre (genre->ds, "feature");
479 if (g_feature != NULL)
481 CONCORD_Feature p_true_name
482 = concord_genre_get_feature_0 (g_feature, "true-name");
484 if (g_feature != NULL)
486 CONCORD_String_Tank s_true_name;
488 = concord_obj_get_feature_value_string (name,
493 unsigned char* t_name = alloca (s_true_name.size + 1);
495 strncpy (t_name, s_true_name.data, s_true_name.size);
496 t_name[s_true_name.size] = '\0';
497 return concord_genre_get_feature_0 (genre, t_name);
501 return concord_genre_get_feature_0 (genre, name);
505 concord_genre_get_index (CONCORD_Genre genre, const unsigned char* name)
509 index = concord_name_table_get (genre->index_names, name);
513 index = concord_genre_open_index (genre, name);
517 if (concord_name_table_put (genre->index_names, name, index))
519 concord_close_index (index);
526 struct CONCORD_Feature_Table
535 concord_genre_open_feature (CONCORD_Genre genre, const unsigned char* feature)
537 CONCORD_Feature table;
538 size_t len = strlen (feature);
543 table = (CONCORD_Feature)malloc (sizeof (CONCORD_Feature_Table));
547 table->genre = genre;
550 table->name = (unsigned char*)malloc (len + 1);
551 if (table->name == NULL)
556 strcpy (table->name, feature);
561 concord_close_feature (CONCORD_Feature feature)
568 if (feature->db == NULL)
571 status = CONCORD_BDB_close (feature->db);
573 if (feature->name == NULL)
577 free (feature->name);
585 concord_feature_get_name (CONCORD_Feature feature)
587 return feature->name;
591 concord_feature_setup_db (CONCORD_Feature feature, int writable)
600 if ((feature->access & DB_CREATE) == 0)
602 if (feature->db != NULL)
604 CONCORD_BDB_close (feature->db);
614 if (feature->db == NULL)
616 CONCORD_Genre genre = feature->genre;
619 = CONCORD_BDB_open (genre->ds->location, genre->name,
620 "feature", feature->name,
622 access, genre->ds->modemask);
623 if (feature->db == NULL)
625 feature->access = access;
631 concord_feature_sync (CONCORD_Feature feature)
635 if (feature->db == NULL)
638 status = CONCORD_BDB_close (feature->db);
645 concord_obj_put_feature_value_str (const unsigned char* object_id,
646 CONCORD_Feature feature,
647 unsigned char* value)
651 if (concord_feature_setup_db (feature, 1))
653 return CONCORD_BDB_put (feature->db, object_id, value);
657 concord_obj_get_feature_value_string (const unsigned char* object_id,
658 CONCORD_Feature feature,
659 CONCORD_String value)
663 if (concord_feature_setup_db (feature, 0))
665 status = CONCORD_BDB_get (feature->db, object_id, value);
670 concord_obj_get_feature_value (const unsigned char* object_id,
671 CONCORD_Feature feature)
676 if (concord_feature_setup_db (feature, 0))
677 return feature->genre->ds->object_nil;
678 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
680 return feature->genre->ds->object_nil;
681 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
685 concord_obj_gets_feature_value (const unsigned char* object_id,
686 CONCORD_Feature feature,
687 unsigned char* dst, size_t size)
692 if (concord_feature_setup_db (feature, 0))
694 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
697 if (size < valdatum.size)
699 strncpy (dst, valdatum.data, valdatum.size);
700 dst[valdatum.size] = '\0';
705 concord_feature_foreach_obj_string (CONCORD_Feature feature,
706 int (*func)(CONCORD_String object_id,
707 CONCORD_Feature feature,
708 CONCORD_String value))
710 CONCORD_String_Tank key, value;
714 if (concord_feature_setup_db (feature, 0))
719 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
720 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
722 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
724 int ret = func (&key, feature, &value);
729 dbcp->c_close (dbcp);
734 struct CONCORD_INDEX_Table
743 concord_genre_open_index (CONCORD_Genre genre, const unsigned char* index)
746 size_t len = strlen (index);
751 table = (CONCORD_INDEX)malloc (sizeof (CONCORD_INDEX_Table));
755 table->genre = genre;
758 table->name = (unsigned char*)malloc (len + 1);
759 if (table->name == NULL)
764 strcpy (table->name, index);
769 concord_close_index (CONCORD_INDEX table)
776 if (table->db == NULL)
779 status = CONCORD_BDB_close (table->db);
781 if (table->name == NULL)
793 concord_index_setup_db (CONCORD_INDEX index, int writable)
802 if ((index->access & DB_CREATE) == 0)
804 if (index->db != NULL)
806 CONCORD_BDB_close (index->db);
816 if (index->db == NULL)
818 CONCORD_Genre genre = index->genre;
821 = CONCORD_BDB_open (genre->ds->location, genre->name,
822 "index", index->name,
824 access, genre->ds->modemask);
825 if (index->db == NULL)
827 index->access = access;
833 concord_index_sync (CONCORD_INDEX index)
837 if (index->db == NULL)
840 status = CONCORD_BDB_close (index->db);
847 concord_index_strid_put_obj (CONCORD_INDEX index,
848 const unsigned char* strid,
849 unsigned char* object_id)
854 if (concord_index_setup_db (index, 1))
857 return CONCORD_BDB_put (index->db, strid, object_id);
861 concord_index_strid_get_obj_string (CONCORD_INDEX index,
862 const unsigned char* strid,
863 CONCORD_String object_id)
868 if (concord_index_setup_db (index, 0))
871 return CONCORD_BDB_get (index->db, strid, object_id);