1 /* Copyright (C) 2003, 2004, 2005, 2006, 2011, 2013 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"
29 #include "concord-bdb.h"
33 CONCORD_String_size (const CONCORD_String s)
39 CONCORD_String_data (const CONCORD_String s)
44 CONCORD_Genre concord_ds_open_genre (CONCORD_DS ds, const char* name);
48 concord_genre_open_feature (CONCORD_Genre genre, const char* name);
52 concord_genre_open_index (CONCORD_Genre genre, const char* index);
55 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name);
59 concord_default_read_object (const unsigned char* string, size_t length);
64 COS_Object_Header header;
65 CONCORD_Backend_Type type;
67 CONCORD_NAME_TABLE* genre_names;
71 CONCORD_Object object_nil;
72 CONCORD_Object (*read_object) (const unsigned char* str, size_t length);
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)
91 CONCORD_DS ds = COS_ALLOCATE_OBJECT (DS);
92 size_t len = strlen (location);
98 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
99 ds->modemask = modemask;
100 ds->location = (char*)malloc (len + 1);
101 if (ds->location == NULL)
102 goto location_failure;
104 strcpy (ds->location, location);
106 ds->genre_names = concord_make_name_table ();
107 if (ds->genre_names == NULL)
115 ds->object_nil = NULL;
116 ds->read_object = &concord_default_read_object;
122 concord_close_ds (CONCORD_DS ds)
124 if (ds->location != NULL)
126 if (ds->genre_names != NULL)
127 concord_destroy_name_table (ds->genre_names);
133 concord_ds_location (CONCORD_DS ds)
139 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
141 ds->object_nil = object_nil;
146 concord_ds_set_read_object_function (CONCORD_DS ds,
147 CONCORD_Object (*read_object)
148 (const unsigned char* str,
151 ds->read_object = read_object;
156 concord_ds_get_genre (CONCORD_DS ds, const char* name)
160 genre = concord_name_table_get (ds->genre_names, name);
164 genre = concord_ds_open_genre (ds, name);
168 if (concord_name_table_put (ds->genre_names, name, genre))
170 concord_close_genre (genre);
177 concord_ds_foreach_genre_name (CONCORD_DS ds,
178 int (*func) (CONCORD_DS ds, char* name))
180 char* dname = ds->location;
184 if ( (dir = opendir (dname)) == NULL)
187 while ( (de = readdir (dir)) != NULL )
189 if ( (strcmp (de->d_name, ".") != 0) &&
190 (strcmp (de->d_name, "..") != 0) )
192 int i, need_to_decode = 0;
197 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
208 name = (char*) alloca (i);
209 cp = (unsigned char*)de->d_name;
210 np = (unsigned char*)name;
212 while ( (ch = *cp++) != '\0')
228 if ( ('0' <= ch) && (ch <= '9') )
229 hex[index++] = ch - '0';
230 else if ( ('A' <= ch) && (ch <= 'F') )
231 hex[index++] = ch - 'A' + 10;
232 else if ( ('a' <= ch) && (ch <= 'f') )
233 hex[index++] = ch - 'a' + 10;
245 *np++ = (hex[0] << 4) | hex[1];
259 return closedir (dir);
262 return closedir (dir);
268 COS_Object_Header header;
271 CONCORD_NAME_TABLE* feature_names;
272 CONCORD_NAME_TABLE* index_names;
276 concord_ds_open_genre (CONCORD_DS ds, const char* name)
279 size_t len = strlen (name);
284 genre = COS_ALLOCATE_OBJECT (Genre);
289 genre->name = (char*)malloc (len + 1);
290 if (genre->name == NULL)
295 strcpy (genre->name, name);
297 genre->feature_names = concord_make_name_table ();
298 if (genre->feature_names == NULL)
305 genre->index_names = concord_make_name_table ();
306 if (genre->index_names == NULL)
308 free (genre->feature_names);
317 concord_close_genre (CONCORD_Genre genre)
324 if (genre->name == NULL)
332 if (genre->feature_names != NULL)
333 concord_destroy_name_table (genre->feature_names);
335 if (genre->index_names != NULL)
336 concord_destroy_name_table (genre->index_names);
343 concord_genre_get_name (CONCORD_Genre genre)
349 concord_genre_get_data_source (CONCORD_Genre genre)
355 concord_genre_foreach_feature_name (CONCORD_Genre genre,
356 int (*func) (CONCORD_Genre genre,
360 = alloca (strlen (genre->ds->location)
361 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
365 strcpy (dname, genre->ds->location);
367 strcat (dname, genre->name);
368 strcat (dname, "/feature");
370 if ( (dir = opendir (dname)) == NULL)
373 while ( (de = readdir (dir)) != NULL )
375 if ( (strcmp (de->d_name, ".") != 0) &&
376 (strcmp (de->d_name, "..") != 0) )
378 int i, need_to_decode = 0;
383 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
394 name = (char*) alloca (i);
395 cp = (unsigned char*)de->d_name;
396 np = (unsigned char*)name;
398 while ( (ch = *cp++) != '\0')
414 if ( ('0' <= ch) && (ch <= '9') )
415 hex[index++] = ch - '0';
416 else if ( ('A' <= ch) && (ch <= 'F') )
417 hex[index++] = ch - 'A' + 10;
418 else if ( ('a' <= ch) && (ch <= 'f') )
419 hex[index++] = ch - 'a' + 10;
431 *np++ = (hex[0] << 4) | hex[1];
444 if (func (genre, name))
445 return closedir (dir);
448 return closedir (dir);
452 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name)
454 CONCORD_Feature feature;
456 feature = concord_name_table_get (genre->feature_names, name);
460 feature = concord_genre_open_feature (genre, name);
464 if (concord_name_table_put (genre->feature_names, name, feature))
466 concord_close_feature (feature);
473 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
475 CONCORD_Genre g_feature
476 = concord_ds_get_genre (genre->ds, "feature");
478 if (g_feature != NULL)
480 CONCORD_Feature p_true_name
481 = concord_genre_get_feature_0 (g_feature, "true-name");
483 if (g_feature != NULL)
485 CONCORD_String_Tank s_true_name;
487 = concord_obj_get_feature_value_string (name,
492 char* t_name = alloca (s_true_name.size + 1);
494 strncpy (t_name, s_true_name.data, s_true_name.size);
495 t_name[s_true_name.size] = '\0';
496 return concord_genre_get_feature_0 (genre, t_name);
500 return concord_genre_get_feature_0 (genre, name);
504 concord_genre_get_index (CONCORD_Genre genre, const char* name)
508 index = concord_name_table_get (genre->index_names, name);
512 index = concord_genre_open_index (genre, name);
516 if (concord_name_table_put (genre->index_names, name, index))
518 concord_close_index (index);
526 concord_genre_open_feature (CONCORD_Genre genre, const char* feature)
528 CONCORD_Feature table;
529 size_t len = strlen (feature);
534 table = COS_ALLOCATE_OBJECT (Feature);
538 table->genre = genre;
541 table->name = (char*)malloc (len + 1);
542 if (table->name == NULL)
547 strcpy (table->name, feature);
548 table->value_table = NULL;
553 concord_close_feature (CONCORD_Feature feature)
560 if (feature->db == NULL)
563 status = CONCORD_BDB_close (feature->db);
565 if (feature->name == NULL)
569 free (feature->name);
577 concord_feature_get_name (CONCORD_Feature feature)
579 return feature->name;
583 concord_feature_get_genre (CONCORD_Feature feature)
585 return feature->genre;
589 concord_feature_setup_db (CONCORD_Feature feature, int writable)
598 if ((feature->access & DB_CREATE) == 0)
600 if (feature->db != NULL)
602 CONCORD_BDB_close (feature->db);
612 if (feature->db == NULL)
614 CONCORD_Genre genre = feature->genre;
617 = CONCORD_BDB_open (genre->ds->location, genre->name,
618 "feature", feature->name,
620 access, genre->ds->modemask);
621 if (feature->db == NULL)
623 feature->access = access;
629 concord_feature_sync (CONCORD_Feature feature)
633 if (feature->db == NULL)
636 status = CONCORD_BDB_close (feature->db);
643 concord_obj_put_feature_value_str (const char* object_id,
644 CONCORD_Feature feature,
645 unsigned char* value)
649 if (concord_feature_setup_db (feature, 1))
651 return CONCORD_BDB_put (feature->db, object_id, value);
655 concord_obj_get_feature_value_string (const char* object_id,
656 CONCORD_Feature feature,
657 CONCORD_String value)
661 if (concord_feature_setup_db (feature, 0))
663 status = CONCORD_BDB_get (feature->db, object_id, value);
668 concord_obj_get_feature_value (const char* object_id,
669 CONCORD_Feature feature)
674 if (concord_feature_setup_db (feature, 0))
675 return feature->genre->ds->object_nil;
676 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
678 return feature->genre->ds->object_nil;
679 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
683 concord_obj_gets_feature_value (const char* object_id,
684 CONCORD_Feature feature,
685 unsigned char* dst, size_t size)
690 if (concord_feature_setup_db (feature, 0))
692 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
695 if (size < valdatum.size)
697 strncpy ((char*)dst, valdatum.data, valdatum.size);
698 dst[valdatum.size] = '\0';
703 concord_feature_foreach_obj_string (CONCORD_Feature feature,
704 int (*func)(CONCORD_String object_id,
705 CONCORD_Feature feature,
706 CONCORD_String value))
708 CONCORD_String_Tank key, value;
712 if (concord_feature_setup_db (feature, 0))
717 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
718 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
720 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
722 int ret = func (&key, feature, &value);
727 dbcp->c_close (dbcp);
733 concord_genre_open_index (CONCORD_Genre genre, const char* index)
736 size_t len = strlen (index);
741 table = COS_ALLOCATE_OBJECT (Feature_INDEX);
745 table->genre = genre;
748 table->name = (char*)malloc (len + 1);
749 if (table->name == NULL)
754 strcpy (table->name, index);
755 table->decoding_table = NULL;
760 concord_close_index (CONCORD_INDEX table)
767 if (table->db == NULL)
770 status = CONCORD_BDB_close (table->db);
772 if (table->name == NULL)
784 concord_index_get_name (CONCORD_INDEX index)
790 concord_index_get_genre (CONCORD_INDEX index)
796 concord_index_setup_db (CONCORD_INDEX index, int writable)
805 if ((index->access & DB_CREATE) == 0)
807 if (index->db != NULL)
809 CONCORD_BDB_close (index->db);
819 if (index->db == NULL)
821 CONCORD_Genre genre = index->genre;
824 = CONCORD_BDB_open (genre->ds->location, genre->name,
825 "index", index->name,
827 access, genre->ds->modemask);
828 if (index->db == NULL)
830 index->access = access;
836 concord_index_sync (CONCORD_INDEX index)
840 if (index->db == NULL)
843 status = CONCORD_BDB_close (index->db);
850 concord_index_strid_put_obj (CONCORD_INDEX index,
851 const char* strid, char* object_id)
856 if (concord_index_setup_db (index, 1))
859 return CONCORD_BDB_put (index->db, strid, (unsigned char*)object_id);
863 concord_index_strid_get_obj_string (CONCORD_INDEX index,
865 CONCORD_String object_id)
870 if (concord_index_setup_db (index, 0))
873 return CONCORD_BDB_get (index->db, strid, object_id);