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"
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);
75 concord_default_read_object (const unsigned char* str, size_t length)
77 unsigned char* buf = malloc (length + 1);
81 strncpy ((char*)buf, (char*)str, length);
83 return (CONCORD_Object)buf;
87 concord_open_ds (CONCORD_Backend_Type type, const char* location,
88 int subtype, int modemask)
90 CONCORD_DS ds = COS_ALLOCATE_OBJECT (DS);
91 size_t len = strlen (location);
97 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
98 ds->modemask = modemask;
99 ds->location = (char*)malloc (len + 1);
100 if (ds->location == NULL)
101 goto location_failure;
103 strcpy (ds->location, location);
105 ds->genre_names = concord_make_name_table ();
106 if (ds->genre_names == NULL)
114 ds->object_nil = NULL;
115 ds->read_object = &concord_default_read_object;
121 concord_close_ds (CONCORD_DS ds)
123 if (ds->location != NULL)
125 if (ds->genre_names != NULL)
126 concord_destroy_name_table (ds->genre_names);
132 concord_ds_location (CONCORD_DS ds)
138 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
140 ds->object_nil = object_nil;
145 concord_ds_set_read_object_function (CONCORD_DS ds,
146 CONCORD_Object (*read_object)
147 (const unsigned char* str,
150 ds->read_object = read_object;
155 concord_ds_get_genre (CONCORD_DS ds, const char* name)
159 genre = concord_name_table_get (ds->genre_names, name);
163 genre = concord_ds_open_genre (ds, name);
167 if (concord_name_table_put (ds->genre_names, name, genre))
169 concord_close_genre (genre);
176 concord_ds_foreach_genre_name (CONCORD_DS ds,
177 int (*func) (CONCORD_DS ds, char* name))
179 char* dname = ds->location;
183 if ( (dir = opendir (dname)) == NULL)
186 while ( (de = readdir (dir)) != NULL )
188 if ( (strcmp (de->d_name, ".") != 0) &&
189 (strcmp (de->d_name, "..") != 0) )
191 int i, need_to_decode = 0;
196 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
207 name = (char*) alloca (i);
208 cp = (unsigned char*)de->d_name;
209 np = (unsigned char*)name;
211 while ( (ch = *cp++) != '\0')
227 if ( ('0' <= ch) && (ch <= '9') )
228 hex[index++] = ch - '0';
229 else if ( ('A' <= ch) && (ch <= 'F') )
230 hex[index++] = ch - 'A' + 10;
231 else if ( ('a' <= ch) && (ch <= 'f') )
232 hex[index++] = ch - 'a' + 10;
244 *np++ = (hex[0] << 4) | hex[1];
258 return closedir (dir);
261 return closedir (dir);
267 COS_Object_Header header;
270 CONCORD_NAME_TABLE* feature_names;
271 CONCORD_NAME_TABLE* index_names;
275 concord_ds_open_genre (CONCORD_DS ds, const char* name)
278 size_t len = strlen (name);
283 genre = COS_ALLOCATE_OBJECT (Genre);
288 genre->name = (char*)malloc (len + 1);
289 if (genre->name == NULL)
294 strcpy (genre->name, name);
296 genre->feature_names = concord_make_name_table ();
297 if (genre->feature_names == NULL)
304 genre->index_names = concord_make_name_table ();
305 if (genre->index_names == NULL)
307 free (genre->feature_names);
316 concord_close_genre (CONCORD_Genre genre)
323 if (genre->name == NULL)
331 if (genre->feature_names != NULL)
332 concord_destroy_name_table (genre->feature_names);
334 if (genre->index_names != NULL)
335 concord_destroy_name_table (genre->index_names);
342 concord_genre_get_name (CONCORD_Genre genre)
348 concord_genre_get_data_source (CONCORD_Genre genre)
354 concord_genre_foreach_feature_name (CONCORD_Genre genre,
355 int (*func) (CONCORD_Genre genre,
359 = alloca (strlen (genre->ds->location)
360 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
364 strcpy (dname, genre->ds->location);
366 strcat (dname, genre->name);
367 strcat (dname, "/feature");
369 if ( (dir = opendir (dname)) == NULL)
372 while ( (de = readdir (dir)) != NULL )
374 if ( (strcmp (de->d_name, ".") != 0) &&
375 (strcmp (de->d_name, "..") != 0) )
377 int i, need_to_decode = 0;
382 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
393 name = (char*) alloca (i);
394 cp = (unsigned char*)de->d_name;
395 np = (unsigned char*)name;
397 while ( (ch = *cp++) != '\0')
413 if ( ('0' <= ch) && (ch <= '9') )
414 hex[index++] = ch - '0';
415 else if ( ('A' <= ch) && (ch <= 'F') )
416 hex[index++] = ch - 'A' + 10;
417 else if ( ('a' <= ch) && (ch <= 'f') )
418 hex[index++] = ch - 'a' + 10;
430 *np++ = (hex[0] << 4) | hex[1];
443 if (func (genre, name))
444 return closedir (dir);
447 return closedir (dir);
451 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name)
453 CONCORD_Feature feature;
455 feature = concord_name_table_get (genre->feature_names, name);
459 feature = concord_genre_open_feature (genre, name);
463 if (concord_name_table_put (genre->feature_names, name, feature))
465 concord_close_feature (feature);
472 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
474 CONCORD_Genre g_feature
475 = concord_ds_get_genre (genre->ds, "feature");
477 if (g_feature != NULL)
479 CONCORD_Feature p_true_name
480 = concord_genre_get_feature_0 (g_feature, "true-name");
482 if (g_feature != NULL)
484 CONCORD_String_Tank s_true_name;
486 = concord_obj_get_feature_value_string (name,
491 char* t_name = alloca (s_true_name.size + 1);
493 strncpy (t_name, s_true_name.data, s_true_name.size);
494 t_name[s_true_name.size] = '\0';
495 return concord_genre_get_feature_0 (genre, t_name);
499 return concord_genre_get_feature_0 (genre, name);
503 concord_genre_get_index (CONCORD_Genre genre, const char* name)
507 index = concord_name_table_get (genre->index_names, name);
511 index = concord_genre_open_index (genre, name);
515 if (concord_name_table_put (genre->index_names, name, index))
517 concord_close_index (index);
524 struct COS_Feature_ent
526 COS_Object_Header header;
534 concord_genre_open_feature (CONCORD_Genre genre, const char* feature)
536 CONCORD_Feature table;
537 size_t len = strlen (feature);
542 table = COS_ALLOCATE_OBJECT (Feature);
546 table->genre = genre;
549 table->name = (char*)malloc (len + 1);
550 if (table->name == NULL)
555 strcpy (table->name, feature);
560 concord_close_feature (CONCORD_Feature feature)
567 if (feature->db == NULL)
570 status = CONCORD_BDB_close (feature->db);
572 if (feature->name == NULL)
576 free (feature->name);
584 concord_feature_get_name (CONCORD_Feature feature)
586 return feature->name;
590 concord_feature_get_genre (CONCORD_Feature feature)
592 return feature->genre;
596 concord_feature_setup_db (CONCORD_Feature feature, int writable)
605 if ((feature->access & DB_CREATE) == 0)
607 if (feature->db != NULL)
609 CONCORD_BDB_close (feature->db);
619 if (feature->db == NULL)
621 CONCORD_Genre genre = feature->genre;
624 = CONCORD_BDB_open (genre->ds->location, genre->name,
625 "feature", feature->name,
627 access, genre->ds->modemask);
628 if (feature->db == NULL)
630 feature->access = access;
636 concord_feature_sync (CONCORD_Feature feature)
640 if (feature->db == NULL)
643 status = CONCORD_BDB_close (feature->db);
650 concord_obj_put_feature_value_str (const char* object_id,
651 CONCORD_Feature feature,
652 unsigned char* value)
656 if (concord_feature_setup_db (feature, 1))
658 return CONCORD_BDB_put (feature->db, object_id, value);
662 concord_obj_get_feature_value_string (const char* object_id,
663 CONCORD_Feature feature,
664 CONCORD_String value)
668 if (concord_feature_setup_db (feature, 0))
670 status = CONCORD_BDB_get (feature->db, object_id, value);
675 concord_obj_get_feature_value (const char* object_id,
676 CONCORD_Feature feature)
681 if (concord_feature_setup_db (feature, 0))
682 return feature->genre->ds->object_nil;
683 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
685 return feature->genre->ds->object_nil;
686 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
690 concord_obj_gets_feature_value (const char* object_id,
691 CONCORD_Feature feature,
692 unsigned char* dst, size_t size)
697 if (concord_feature_setup_db (feature, 0))
699 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
702 if (size < valdatum.size)
704 strncpy ((char*)dst, valdatum.data, valdatum.size);
705 dst[valdatum.size] = '\0';
710 concord_feature_foreach_obj_string (CONCORD_Feature feature,
711 int (*func)(CONCORD_String object_id,
712 CONCORD_Feature feature,
713 CONCORD_String value))
715 CONCORD_String_Tank key, value;
719 if (concord_feature_setup_db (feature, 0))
724 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
725 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
727 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
729 int ret = func (&key, feature, &value);
734 dbcp->c_close (dbcp);
739 struct COS_Feature_INDEX_ent
741 COS_Object_Header header;
749 concord_genre_open_index (CONCORD_Genre genre, const char* index)
752 size_t len = strlen (index);
757 table = COS_ALLOCATE_OBJECT (Feature_INDEX);
761 table->genre = genre;
764 table->name = (char*)malloc (len + 1);
765 if (table->name == NULL)
770 strcpy (table->name, index);
775 concord_close_index (CONCORD_INDEX table)
782 if (table->db == NULL)
785 status = CONCORD_BDB_close (table->db);
787 if (table->name == NULL)
799 concord_index_get_name (CONCORD_INDEX index)
805 concord_index_get_genre (CONCORD_INDEX index)
811 concord_index_setup_db (CONCORD_INDEX index, int writable)
820 if ((index->access & DB_CREATE) == 0)
822 if (index->db != NULL)
824 CONCORD_BDB_close (index->db);
834 if (index->db == NULL)
836 CONCORD_Genre genre = index->genre;
839 = CONCORD_BDB_open (genre->ds->location, genre->name,
840 "index", index->name,
842 access, genre->ds->modemask);
843 if (index->db == NULL)
845 index->access = access;
851 concord_index_sync (CONCORD_INDEX index)
855 if (index->db == NULL)
858 status = CONCORD_BDB_close (index->db);
865 concord_index_strid_put_obj (CONCORD_INDEX index,
866 const char* strid, char* object_id)
871 if (concord_index_setup_db (index, 1))
874 return CONCORD_BDB_put (index->db, strid, (unsigned char*)object_id);
878 concord_index_strid_get_obj_string (CONCORD_INDEX index,
880 CONCORD_String object_id)
885 if (concord_index_setup_db (index, 0))
888 return CONCORD_BDB_get (index->db, strid, object_id);