1 /* Copyright (C) 2003,2004,2005,2006 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 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 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, char* name))
187 unsigned char* dname = ds->location;
191 if ( (dir = opendir (dname)) == NULL)
194 while ( (de = readdir (dir)) != NULL )
196 if ( (strcmp (de->d_name, ".") != 0) &&
197 (strcmp (de->d_name, "..") != 0) )
199 int i, need_to_decode = 0;
204 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
215 name = (unsigned char *) alloca (i);
219 while ( (ch = *cp++) != '\0')
235 if ( ('0' <= ch) && (ch <= '9') )
236 hex[index++] = ch - '0';
237 else if ( ('A' <= ch) && (ch <= 'F') )
238 hex[index++] = ch - 'A' + 10;
239 else if ( ('a' <= ch) && (ch <= 'f') )
240 hex[index++] = ch - 'a' + 10;
252 *np++ = (hex[0] << 4) | hex[1];
266 return closedir (dir);
269 return closedir (dir);
273 struct CONCORD_Genre_Table
277 CONCORD_NAME_TABLE* feature_names;
278 CONCORD_NAME_TABLE* index_names;
282 concord_ds_open_genre (CONCORD_DS ds, const unsigned char* name)
285 size_t len = strlen (name);
290 genre = (CONCORD_Genre)malloc (sizeof (CONCORD_Genre_Table));
295 genre->name = (unsigned char*)malloc (len + 1);
296 if (genre->name == NULL)
301 strcpy (genre->name, name);
303 genre->feature_names = concord_make_name_table ();
304 if (genre->feature_names == NULL)
311 genre->index_names = concord_make_name_table ();
312 if (genre->index_names == NULL)
314 free (genre->feature_names);
323 concord_close_genre (CONCORD_Genre genre)
330 if (genre->name == NULL)
338 if (genre->feature_names != NULL)
339 concord_destroy_name_table (genre->feature_names);
341 if (genre->index_names != NULL)
342 concord_destroy_name_table (genre->index_names);
349 concord_genre_get_name (CONCORD_Genre genre)
355 concord_genre_get_data_source (CONCORD_Genre genre)
361 concord_genre_foreach_feature_name (CONCORD_Genre genre,
362 int (*func) (CONCORD_Genre genre,
366 = alloca (strlen (genre->ds->location)
367 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
371 strcpy (dname, genre->ds->location);
373 strcat (dname, genre->name);
374 strcat (dname, "/feature");
376 if ( (dir = opendir (dname)) == NULL)
379 while ( (de = readdir (dir)) != NULL )
381 if ( (strcmp (de->d_name, ".") != 0) &&
382 (strcmp (de->d_name, "..") != 0) )
384 int i, need_to_decode = 0;
389 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
400 name = (unsigned char *) alloca (i);
404 while ( (ch = *cp++) != '\0')
420 if ( ('0' <= ch) && (ch <= '9') )
421 hex[index++] = ch - '0';
422 else if ( ('A' <= ch) && (ch <= 'F') )
423 hex[index++] = ch - 'A' + 10;
424 else if ( ('a' <= ch) && (ch <= 'f') )
425 hex[index++] = ch - 'a' + 10;
437 *np++ = (hex[0] << 4) | hex[1];
450 if (func (genre, name))
451 return closedir (dir);
454 return closedir (dir);
458 concord_genre_get_feature_0 (CONCORD_Genre genre, const unsigned char* name)
460 CONCORD_Feature feature;
462 feature = concord_name_table_get (genre->feature_names, name);
466 feature = concord_genre_open_feature (genre, name);
470 if (concord_name_table_put (genre->feature_names, name, feature))
472 concord_close_feature (feature);
479 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
481 CONCORD_Genre g_feature
482 = concord_ds_get_genre (genre->ds, "feature");
484 if (g_feature != NULL)
486 CONCORD_Feature p_true_name
487 = concord_genre_get_feature_0 (g_feature, "true-name");
489 if (g_feature != NULL)
491 CONCORD_String_Tank s_true_name;
493 = concord_obj_get_feature_value_string (name,
498 unsigned char* t_name = alloca (s_true_name.size + 1);
500 strncpy (t_name, s_true_name.data, s_true_name.size);
501 t_name[s_true_name.size] = '\0';
502 return concord_genre_get_feature_0 (genre, t_name);
506 return concord_genre_get_feature_0 (genre, name);
510 concord_genre_get_index (CONCORD_Genre genre, const char* name)
514 index = concord_name_table_get (genre->index_names, name);
518 index = concord_genre_open_index (genre, name);
522 if (concord_name_table_put (genre->index_names, name, index))
524 concord_close_index (index);
531 struct CONCORD_Feature_Table
540 concord_genre_open_feature (CONCORD_Genre genre, const unsigned char* feature)
542 CONCORD_Feature table;
543 size_t len = strlen (feature);
548 table = (CONCORD_Feature)malloc (sizeof (CONCORD_Feature_Table));
552 table->genre = genre;
555 table->name = (unsigned char*)malloc (len + 1);
556 if (table->name == NULL)
561 strcpy (table->name, feature);
566 concord_close_feature (CONCORD_Feature feature)
573 if (feature->db == NULL)
576 status = CONCORD_BDB_close (feature->db);
578 if (feature->name == NULL)
582 free (feature->name);
590 concord_feature_get_name (CONCORD_Feature feature)
592 return feature->name;
596 concord_feature_get_genre (CONCORD_Feature feature)
598 return feature->genre;
602 concord_feature_setup_db (CONCORD_Feature feature, int writable)
611 if ((feature->access & DB_CREATE) == 0)
613 if (feature->db != NULL)
615 CONCORD_BDB_close (feature->db);
625 if (feature->db == NULL)
627 CONCORD_Genre genre = feature->genre;
630 = CONCORD_BDB_open (genre->ds->location, genre->name,
631 "feature", feature->name,
633 access, genre->ds->modemask);
634 if (feature->db == NULL)
636 feature->access = access;
642 concord_feature_sync (CONCORD_Feature feature)
646 if (feature->db == NULL)
649 status = CONCORD_BDB_close (feature->db);
656 concord_obj_put_feature_value_str (const char* object_id,
657 CONCORD_Feature feature,
658 unsigned char* value)
662 if (concord_feature_setup_db (feature, 1))
664 return CONCORD_BDB_put (feature->db, object_id, value);
668 concord_obj_get_feature_value_string (const char* object_id,
669 CONCORD_Feature feature,
670 CONCORD_String value)
674 if (concord_feature_setup_db (feature, 0))
676 status = CONCORD_BDB_get (feature->db, object_id, value);
681 concord_obj_get_feature_value (const char* object_id,
682 CONCORD_Feature feature)
687 if (concord_feature_setup_db (feature, 0))
688 return feature->genre->ds->object_nil;
689 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
691 return feature->genre->ds->object_nil;
692 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
696 concord_obj_gets_feature_value (const char* object_id,
697 CONCORD_Feature feature,
698 unsigned char* dst, size_t size)
703 if (concord_feature_setup_db (feature, 0))
705 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
708 if (size < valdatum.size)
710 strncpy (dst, valdatum.data, valdatum.size);
711 dst[valdatum.size] = '\0';
716 concord_feature_foreach_obj_string (CONCORD_Feature feature,
717 int (*func)(CONCORD_String object_id,
718 CONCORD_Feature feature,
719 CONCORD_String value))
721 CONCORD_String_Tank key, value;
725 if (concord_feature_setup_db (feature, 0))
730 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
731 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
733 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
735 int ret = func (&key, feature, &value);
740 dbcp->c_close (dbcp);
745 struct CONCORD_INDEX_Table
754 concord_genre_open_index (CONCORD_Genre genre, const unsigned char* index)
757 size_t len = strlen (index);
762 table = (CONCORD_INDEX)malloc (sizeof (CONCORD_INDEX_Table));
766 table->genre = genre;
769 table->name = (unsigned char*)malloc (len + 1);
770 if (table->name == NULL)
775 strcpy (table->name, index);
780 concord_close_index (CONCORD_INDEX table)
787 if (table->db == NULL)
790 status = CONCORD_BDB_close (table->db);
792 if (table->name == NULL)
804 concord_index_setup_db (CONCORD_INDEX index, int writable)
813 if ((index->access & DB_CREATE) == 0)
815 if (index->db != NULL)
817 CONCORD_BDB_close (index->db);
827 if (index->db == NULL)
829 CONCORD_Genre genre = index->genre;
832 = CONCORD_BDB_open (genre->ds->location, genre->name,
833 "index", index->name,
835 access, genre->ds->modemask);
836 if (index->db == NULL)
838 index->access = access;
844 concord_index_sync (CONCORD_INDEX index)
848 if (index->db == NULL)
851 status = CONCORD_BDB_close (index->db);
858 concord_index_strid_put_obj (CONCORD_INDEX index,
859 const char* strid, char* object_id)
864 if (concord_index_setup_db (index, 1))
867 return CONCORD_BDB_put (index->db, strid, object_id);
871 concord_index_strid_get_obj_string (CONCORD_INDEX index,
873 CONCORD_String object_id)
878 if (concord_index_setup_db (index, 0))
881 return CONCORD_BDB_get (index->db, strid, object_id);