1 /* Copyright (C) 2003,2004,2005,2006,2011 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)
45 CONCORD_Genre concord_ds_open_genre (CONCORD_DS ds, const char* name);
47 int concord_close_genre (CONCORD_Genre genre);
51 concord_genre_open_feature (CONCORD_Genre genre, const char* name);
53 int concord_close_feature (CONCORD_Feature feature);
57 concord_genre_open_index (CONCORD_Genre genre, const char* index);
60 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name);
62 int concord_close_index (CONCORD_INDEX table);
66 concord_default_read_object (const unsigned char* string, size_t length);
69 typedef struct CONCORD_Object_Header
73 } CONCORD_Object_Header;
75 #define CONCORD_OBJECT_TYPE_NULL 0
76 #define CONCORD_OBJECT_TYPE_C_STRING 1
77 #define CONCORD_OBJECT_TYPE_INT 2
78 #define CONCORD_OBJECT_TYPE_DS 16
79 #define CONCORD_OBJECT_TYPE_GENRE 17
80 #define CONCORD_OBJECT_TYPE_FEATURE 18
81 #define CONCORD_OBJECT_TYPE_INDEX 19
82 #define CONCORD_OBJECT_TYPE_OBJECT 128
85 struct CONCORD_DS_Table
87 CONCORD_Object_Header header;
88 CONCORD_Backend_Type type;
90 CONCORD_NAME_TABLE* genre_names;
94 CONCORD_Object object_nil;
95 CONCORD_Object (*read_object) (const unsigned char* str, size_t length);
99 concord_default_read_object (const unsigned char* str, size_t length)
101 unsigned char* buf = malloc (length + 1);
105 strncpy ((char*)buf, (char*)str, length);
111 concord_open_ds (CONCORD_Backend_Type type, const char* location,
112 int subtype, int modemask)
114 CONCORD_DS ds = (CONCORD_DS)malloc (sizeof (CONCORD_DS_Table));
115 size_t len = strlen (location);
120 ds->header.prefix = 0xff;
121 ds->header.type = CONCORD_OBJECT_TYPE_DS;
123 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
124 ds->modemask = modemask;
125 ds->location = (char*)malloc (len + 1);
126 if (ds->location == NULL)
127 goto location_failure;
129 strcpy (ds->location, location);
131 ds->genre_names = concord_make_name_table ();
132 if (ds->genre_names == NULL)
140 ds->object_nil = NULL;
141 ds->read_object = &concord_default_read_object;
147 concord_close_ds (CONCORD_DS ds)
149 if (ds->location != NULL)
151 if (ds->genre_names != NULL)
152 concord_destroy_name_table (ds->genre_names);
158 concord_ds_location (CONCORD_DS ds)
164 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
166 ds->object_nil = object_nil;
171 concord_ds_set_read_object_function (CONCORD_DS ds,
172 CONCORD_Object (*read_object)
173 (const unsigned char* str,
176 ds->read_object = read_object;
181 concord_ds_get_genre (CONCORD_DS ds, const char* name)
185 genre = concord_name_table_get (ds->genre_names, name);
189 genre = concord_ds_open_genre (ds, name);
193 if (concord_name_table_put (ds->genre_names, name, genre))
195 concord_close_genre (genre);
202 concord_ds_foreach_genre_name (CONCORD_DS ds,
203 int (*func) (CONCORD_DS ds, char* name))
205 char* dname = ds->location;
209 if ( (dir = opendir (dname)) == NULL)
212 while ( (de = readdir (dir)) != NULL )
214 if ( (strcmp (de->d_name, ".") != 0) &&
215 (strcmp (de->d_name, "..") != 0) )
217 int i, need_to_decode = 0;
222 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
233 name = (char*) alloca (i);
234 cp = (unsigned char*)de->d_name;
235 np = (unsigned char*)name;
237 while ( (ch = *cp++) != '\0')
253 if ( ('0' <= ch) && (ch <= '9') )
254 hex[index++] = ch - '0';
255 else if ( ('A' <= ch) && (ch <= 'F') )
256 hex[index++] = ch - 'A' + 10;
257 else if ( ('a' <= ch) && (ch <= 'f') )
258 hex[index++] = ch - 'a' + 10;
270 *np++ = (hex[0] << 4) | hex[1];
284 return closedir (dir);
287 return closedir (dir);
291 struct CONCORD_Genre_Table
293 CONCORD_Object_Header header;
296 CONCORD_NAME_TABLE* feature_names;
297 CONCORD_NAME_TABLE* index_names;
301 concord_ds_open_genre (CONCORD_DS ds, const char* name)
304 size_t len = strlen (name);
309 genre = (CONCORD_Genre)malloc (sizeof (CONCORD_Genre_Table));
313 genre->header.prefix = 0xff;
314 genre->header.type = CONCORD_OBJECT_TYPE_GENRE;
316 genre->name = (char*)malloc (len + 1);
317 if (genre->name == NULL)
322 strcpy (genre->name, name);
324 genre->feature_names = concord_make_name_table ();
325 if (genre->feature_names == NULL)
332 genre->index_names = concord_make_name_table ();
333 if (genre->index_names == NULL)
335 free (genre->feature_names);
344 concord_close_genre (CONCORD_Genre genre)
351 if (genre->name == NULL)
359 if (genre->feature_names != NULL)
360 concord_destroy_name_table (genre->feature_names);
362 if (genre->index_names != NULL)
363 concord_destroy_name_table (genre->index_names);
370 concord_genre_get_name (CONCORD_Genre genre)
376 concord_genre_get_data_source (CONCORD_Genre genre)
382 concord_genre_foreach_feature_name (CONCORD_Genre genre,
383 int (*func) (CONCORD_Genre genre,
387 = alloca (strlen (genre->ds->location)
388 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
392 strcpy (dname, genre->ds->location);
394 strcat (dname, genre->name);
395 strcat (dname, "/feature");
397 if ( (dir = opendir (dname)) == NULL)
400 while ( (de = readdir (dir)) != NULL )
402 if ( (strcmp (de->d_name, ".") != 0) &&
403 (strcmp (de->d_name, "..") != 0) )
405 int i, need_to_decode = 0;
410 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
421 name = (char*) alloca (i);
422 cp = (unsigned char*)de->d_name;
423 np = (unsigned char*)name;
425 while ( (ch = *cp++) != '\0')
441 if ( ('0' <= ch) && (ch <= '9') )
442 hex[index++] = ch - '0';
443 else if ( ('A' <= ch) && (ch <= 'F') )
444 hex[index++] = ch - 'A' + 10;
445 else if ( ('a' <= ch) && (ch <= 'f') )
446 hex[index++] = ch - 'a' + 10;
458 *np++ = (hex[0] << 4) | hex[1];
471 if (func (genre, name))
472 return closedir (dir);
475 return closedir (dir);
479 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name)
481 CONCORD_Feature feature;
483 feature = concord_name_table_get (genre->feature_names, name);
487 feature = concord_genre_open_feature (genre, name);
491 if (concord_name_table_put (genre->feature_names, name, feature))
493 concord_close_feature (feature);
500 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
502 CONCORD_Genre g_feature
503 = concord_ds_get_genre (genre->ds, "feature");
505 if (g_feature != NULL)
507 CONCORD_Feature p_true_name
508 = concord_genre_get_feature_0 (g_feature, "true-name");
510 if (g_feature != NULL)
512 CONCORD_String_Tank s_true_name;
514 = concord_obj_get_feature_value_string (name,
519 char* t_name = alloca (s_true_name.size + 1);
521 strncpy (t_name, s_true_name.data, s_true_name.size);
522 t_name[s_true_name.size] = '\0';
523 return concord_genre_get_feature_0 (genre, t_name);
527 return concord_genre_get_feature_0 (genre, name);
531 concord_genre_get_index (CONCORD_Genre genre, const char* name)
535 index = concord_name_table_get (genre->index_names, name);
539 index = concord_genre_open_index (genre, name);
543 if (concord_name_table_put (genre->index_names, name, index))
545 concord_close_index (index);
552 struct CONCORD_Feature_Table
554 CONCORD_Object_Header header;
562 concord_genre_open_feature (CONCORD_Genre genre, const char* feature)
564 CONCORD_Feature table;
565 size_t len = strlen (feature);
570 table = (CONCORD_Feature)malloc (sizeof (CONCORD_Feature_Table));
574 table->header.prefix = 0xff;
575 table->header.type = CONCORD_OBJECT_TYPE_FEATURE;
576 table->genre = genre;
579 table->name = (char*)malloc (len + 1);
580 if (table->name == NULL)
585 strcpy (table->name, feature);
590 concord_close_feature (CONCORD_Feature feature)
597 if (feature->db == NULL)
600 status = CONCORD_BDB_close (feature->db);
602 if (feature->name == NULL)
606 free (feature->name);
614 concord_feature_get_name (CONCORD_Feature feature)
616 return feature->name;
620 concord_feature_get_genre (CONCORD_Feature feature)
622 return feature->genre;
626 concord_feature_setup_db (CONCORD_Feature feature, int writable)
635 if ((feature->access & DB_CREATE) == 0)
637 if (feature->db != NULL)
639 CONCORD_BDB_close (feature->db);
649 if (feature->db == NULL)
651 CONCORD_Genre genre = feature->genre;
654 = CONCORD_BDB_open (genre->ds->location, genre->name,
655 "feature", feature->name,
657 access, genre->ds->modemask);
658 if (feature->db == NULL)
660 feature->access = access;
666 concord_feature_sync (CONCORD_Feature feature)
670 if (feature->db == NULL)
673 status = CONCORD_BDB_close (feature->db);
680 concord_obj_put_feature_value_str (const char* object_id,
681 CONCORD_Feature feature,
682 unsigned char* value)
686 if (concord_feature_setup_db (feature, 1))
688 return CONCORD_BDB_put (feature->db, object_id, value);
692 concord_obj_get_feature_value_string (const char* object_id,
693 CONCORD_Feature feature,
694 CONCORD_String value)
698 if (concord_feature_setup_db (feature, 0))
700 status = CONCORD_BDB_get (feature->db, object_id, value);
705 concord_obj_get_feature_value (const char* object_id,
706 CONCORD_Feature feature)
711 if (concord_feature_setup_db (feature, 0))
712 return feature->genre->ds->object_nil;
713 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
715 return feature->genre->ds->object_nil;
716 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
720 concord_obj_gets_feature_value (const char* object_id,
721 CONCORD_Feature feature,
722 unsigned char* dst, size_t size)
727 if (concord_feature_setup_db (feature, 0))
729 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
732 if (size < valdatum.size)
734 strncpy ((char*)dst, valdatum.data, valdatum.size);
735 dst[valdatum.size] = '\0';
740 concord_feature_foreach_obj_string (CONCORD_Feature feature,
741 int (*func)(CONCORD_String object_id,
742 CONCORD_Feature feature,
743 CONCORD_String value))
745 CONCORD_String_Tank key, value;
749 if (concord_feature_setup_db (feature, 0))
754 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
755 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
757 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
759 int ret = func (&key, feature, &value);
764 dbcp->c_close (dbcp);
769 struct CONCORD_INDEX_Table
771 CONCORD_Object_Header header;
779 concord_genre_open_index (CONCORD_Genre genre, const char* index)
782 size_t len = strlen (index);
787 table = (CONCORD_INDEX)malloc (sizeof (CONCORD_INDEX_Table));
791 table->header.prefix = 0xff;
792 table->header.type = CONCORD_OBJECT_TYPE_INDEX;
793 table->genre = genre;
796 table->name = (char*)malloc (len + 1);
797 if (table->name == NULL)
802 strcpy (table->name, index);
807 concord_close_index (CONCORD_INDEX table)
814 if (table->db == NULL)
817 status = CONCORD_BDB_close (table->db);
819 if (table->name == NULL)
831 concord_index_setup_db (CONCORD_INDEX index, int writable)
840 if ((index->access & DB_CREATE) == 0)
842 if (index->db != NULL)
844 CONCORD_BDB_close (index->db);
854 if (index->db == NULL)
856 CONCORD_Genre genre = index->genre;
859 = CONCORD_BDB_open (genre->ds->location, genre->name,
860 "index", index->name,
862 access, genre->ds->modemask);
863 if (index->db == NULL)
865 index->access = access;
871 concord_index_sync (CONCORD_INDEX index)
875 if (index->db == NULL)
878 status = CONCORD_BDB_close (index->db);
885 concord_index_strid_put_obj (CONCORD_INDEX index,
886 const char* strid, char* object_id)
891 if (concord_index_setup_db (index, 1))
894 return CONCORD_BDB_put (index->db, strid, (unsigned char*)object_id);
898 concord_index_strid_get_obj_string (CONCORD_INDEX index,
900 CONCORD_String object_id)
905 if (concord_index_setup_db (index, 0))
908 return CONCORD_BDB_get (index->db, strid, object_id);