1 /* Copyright (C) 2003,2004 MORIOKA Tomohiko
2 This file is part of the CHISE Library.
4 The CHISE 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 CHISE 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 CHISE 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 "chise-name.h"
31 const unsigned char chise_db_dir[] = CHISE_DB_DIR;
32 const unsigned char chise_system_db_dir[] = CHISE_SI_DB_DIR;
35 chise_ds_open_feature_table (CHISE_DS *ds, const char *feature);
37 int chise_ft_close (CHISE_Feature_Table *table);
41 chise_ds_open_ccs_table (CHISE_DS *ds, const char *ccs);
43 int chise_ccst_close (CHISE_CCS_Table *table);
47 chise_ds_open_property_table (CHISE_DS *ds, const char *property);
49 int chise_pt_close (CHISE_Property_Table *table);
52 typedef DB CHISE_Attribute_Table;
54 CHISE_Attribute_Table*
55 CHISE_Attribute_Table_open (const unsigned char *db_dir,
57 const char *key_type, const char *name,
59 u_int32_t accessmask, int modemask);
61 int CHISE_Attribute_Table_close (CHISE_Attribute_Table *db);
63 int chise_attribute_table_get (CHISE_Attribute_Table *db,
64 char *key, CHISE_Value *valdatum);
66 int chise_attribute_table_put (CHISE_Attribute_Table *db,
67 char *key, unsigned char *value);
70 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
73 chise_char_id_parse_c_string (unsigned char *str, size_t len);
76 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len);
82 unsigned char *location;
83 CHISE_NAME_TABLE* feature_names;
84 CHISE_NAME_TABLE* ccs_names;
85 CHISE_NAME_TABLE* property_names;
91 CHISE_DS_open (CHISE_DS_Type type, const unsigned char *location,
92 int subtype, int modemask)
94 CHISE_DS *ds = (CHISE_DS*)malloc (sizeof (CHISE_DS));
95 size_t len = strlen (location);
101 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
102 ds->modemask = modemask;
103 ds->location = (unsigned char*)malloc (len + 1);
104 if (ds->location == NULL)
109 strcpy (ds->location, location);
111 ds->feature_names = chise_make_name_table ();
112 if (ds->feature_names == NULL)
118 ds->ccs_names = chise_make_name_table ();
119 if (ds->ccs_names == NULL)
121 free (ds->feature_names);
126 ds->property_names = chise_make_name_table ();
127 if (ds->property_names == NULL)
129 free (ds->ccs_names);
130 free (ds->feature_names);
138 CHISE_DS_close (CHISE_DS *ds)
140 if (ds->location != NULL)
142 if (ds->feature_names != NULL)
143 chise_destroy_name_table (ds->feature_names);
144 if (ds->ccs_names != NULL)
145 chise_destroy_name_table (ds->ccs_names);
146 if (ds->property_names != NULL)
147 chise_destroy_name_table (ds->property_names);
153 chise_ds_location (CHISE_DS *ds)
159 chise_ds_get_feature (CHISE_DS *ds, const unsigned char *feature)
161 CHISE_Feature_Table* ft;
163 ft = chise_name_table_get (ds->feature_names, feature);
167 ft = chise_ds_open_feature_table (ds, feature);
171 if (chise_name_table_put (ds->feature_names, feature, ft))
180 chise_ds_get_ccs (CHISE_DS *ds, const unsigned char *ccs)
184 ct = chise_name_table_get (ds->ccs_names, ccs);
188 ct = chise_ds_open_ccs_table (ds, ccs);
192 if (chise_name_table_put (ds->ccs_names, ccs, ct))
194 chise_ccst_close (ct);
200 CHISE_Property_Table*
201 chise_ds_get_property (CHISE_DS *ds, const unsigned char *property)
203 CHISE_Property_Table* pt;
205 pt = chise_name_table_get (ds->property_names, property);
209 pt = chise_ds_open_property_table (ds, property);
213 if (chise_name_table_put (ds->property_names, property, pt))
222 chise_ds_foreach_char_feature_name (CHISE_DS *ds,
223 int (*func) (CHISE_DS *ds,
224 unsigned char *name))
227 = alloca (strlen (ds->location) + sizeof ("/character/feature") + 1);
231 strcpy (dname, ds->location);
232 strcat (dname, "/character/feature");
234 if ( (dir = opendir (dname)) == NULL)
237 while ( (de = readdir (dir)) != NULL )
239 if ( (strcmp (de->d_name, ".") != 0) &&
240 (strcmp (de->d_name, "..") != 0) )
242 int i, need_to_decode = 0;
247 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
258 name = (unsigned char *) alloca (i);
262 while ( (ch = *cp++) != '\0')
278 if ( ('0' <= ch) && (ch <= '9') )
279 hex[index++] = ch - '0';
280 else if ( ('A' <= ch) && (ch <= 'F') )
281 hex[index++] = ch - 'A' + 10;
282 else if ( ('a' <= ch) && (ch <= 'f') )
283 hex[index++] = ch - 'a' + 10;
295 *np++ = (hex[0] << 4) | hex[1];
309 return closedir (dir);
312 return closedir (dir);
315 struct CHISE_Feature_Table
319 CHISE_Attribute_Table *db;
324 chise_ds_open_feature_table (CHISE_DS *ds, const char *feature)
326 CHISE_Feature_Table* table;
327 size_t len = strlen (feature);
332 table = (CHISE_Feature_Table*)malloc (sizeof (CHISE_Feature_Table));
339 table->name = (unsigned char*)malloc (len + 1);
340 if (table->name == NULL)
345 strcpy (table->name, feature);
350 chise_ft_close (CHISE_Feature_Table *table)
357 if (table->db == NULL)
360 status = CHISE_Attribute_Table_close (table->db);
362 if (table->name == NULL)
374 chise_feature_setup_db (CHISE_Feature feature, int writable)
383 if ((feature->access & DB_CREATE) == 0)
385 if (feature->db != NULL)
387 CHISE_Attribute_Table_close (feature->db);
397 if (feature->db == NULL)
399 CHISE_DS *ds = feature->ds;
402 = CHISE_Attribute_Table_open (ds->location, "character",
403 "feature", feature->name,
404 ds->subtype, access, ds->modemask);
405 if (feature->db == NULL)
407 feature->access = access;
413 chise_feature_sync (CHISE_Feature feature)
417 if (feature->db == NULL)
420 status = CHISE_Attribute_Table_close (feature->db);
427 chise_char_set_feature_value (CHISE_Char_ID cid,
428 CHISE_Feature feature,
429 unsigned char *value)
431 unsigned char key_buf[8];
435 if (chise_feature_setup_db (feature, 1))
437 chise_format_char_id (cid, key_buf, 8);
438 return chise_attribute_table_put (feature->db, key_buf, value);
442 chise_char_load_feature_value (CHISE_Char_ID cid,
443 CHISE_Feature_Table *table,
444 CHISE_Value *valdatum)
446 unsigned char key_buf[8];
448 if (chise_feature_setup_db (table, 0))
450 chise_format_char_id (cid, key_buf, 8);
451 return chise_attribute_table_get (table->db, key_buf, valdatum);
455 chise_char_gets_feature_value (CHISE_Char_ID cid,
456 CHISE_Feature_Table *table,
457 unsigned char *buf, size_t size)
459 CHISE_Value valdatum;
460 unsigned char key_buf[8];
463 if (chise_feature_setup_db (table, 0))
465 chise_format_char_id (cid, key_buf, 8);
466 status = chise_attribute_table_get (table->db,
470 if (size < valdatum.size)
472 strncpy (buf, valdatum.data, valdatum.size);
473 buf[valdatum.size] = '\0';
478 chise_feature_foreach_char_with_value (CHISE_Feature feature,
479 int (*func) (CHISE_Char_ID cid,
480 CHISE_Feature feature,
481 CHISE_Value *valdatum))
483 DBT keydatum, valdatum;
487 if (chise_feature_setup_db (feature, 0))
492 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
493 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST);
495 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT))
497 unsigned char *key_str = (unsigned char *)keydatum.data;
498 int key_len = strnlen (key_str, keydatum.size);
499 CHISE_Char_ID key = chise_char_id_parse_c_string (key_str, key_len);
500 int ret = func (key, feature, &valdatum);
505 dbcp->c_close (dbcp);
510 struct CHISE_CCS_Table
514 CHISE_Attribute_Table *db;
519 chise_ds_open_ccs_table (CHISE_DS *ds, const char *ccs)
521 CHISE_CCS_Table* table;
522 size_t len = strlen (ccs);
527 table = (CHISE_CCS_Table*)malloc (sizeof (CHISE_CCS_Table));
534 table->name = (unsigned char*)malloc (len + 1);
535 if (table->name == NULL)
540 strcpy (table->name, ccs);
545 chise_ccst_close (CHISE_CCS_Table *table)
552 if (table->db == NULL)
555 status = CHISE_Attribute_Table_close (table->db);
557 if (table->name == NULL)
569 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
578 if ((ccs->access & DB_CREATE) == 0)
582 CHISE_Attribute_Table_close (ccs->db);
594 CHISE_DS *ds = ccs->ds;
597 = CHISE_Attribute_Table_open (ds->location, "character",
598 "by_feature", ccs->name,
599 ds->subtype, access, ds->modemask);
602 ccs->access = access;
608 chise_ccs_sync (CHISE_CCS ccs)
615 status = CHISE_Attribute_Table_close (ccs->db);
622 chise_ccs_decode (CHISE_CCS ccs, int code_point)
624 CHISE_Value valdatum;
631 if (chise_ccs_setup_db (ccs, 0))
634 sprintf(key_buf, "%d", code_point);
635 status = chise_attribute_table_get (ccs->db, key_buf, &valdatum);
639 = (unsigned char *)chise_value_data (&valdatum);
640 int len = strnlen (str, chise_value_size (&valdatum));
642 return chise_char_id_parse_c_string (str, len);
648 chise_ccs_set_decoded_char (CHISE_CCS ccs,
649 int code_point, CHISE_Char_ID cid)
651 char key_buf[16], val_buf[8];
656 if (chise_ccs_setup_db (ccs, 1))
659 sprintf(key_buf, "%d", code_point);
660 chise_format_char_id (cid, val_buf, 8);
661 return chise_attribute_table_put (ccs->db, key_buf, val_buf);
665 struct CHISE_Property_Table
669 CHISE_Attribute_Table *db;
673 CHISE_Property_Table*
674 chise_ds_open_property_table (CHISE_DS *ds, const char *property)
676 CHISE_Property_Table* table;
677 size_t len = strlen (property);
682 table = (CHISE_Property_Table*)malloc (sizeof (CHISE_Property_Table));
689 table->name = (unsigned char*)malloc (len + 1);
690 if (table->name == NULL)
695 strcpy (table->name, property);
700 chise_pt_close (CHISE_Property_Table *table)
707 if (table->db == NULL)
710 status = CHISE_Attribute_Table_close (table->db);
712 if (table->name == NULL)
724 chise_property_setup_db (CHISE_Property property, int writable)
728 if (property == NULL)
733 if ((property->access & DB_CREATE) == 0)
735 if (property->db != NULL)
737 CHISE_Attribute_Table_close (property->db);
740 property->access = 0;
747 if (property->db == NULL)
749 CHISE_DS *ds = property->ds;
752 = CHISE_Attribute_Table_open (ds->location, "feature",
753 "property", property->name,
754 ds->subtype, access, ds->modemask);
755 if (property->db == NULL)
757 property->access = access;
763 chise_property_sync (CHISE_Property property)
767 if (property->db == NULL)
770 status = CHISE_Attribute_Table_close (property->db);
772 property->access = 0;
777 chise_feature_set_property_value (CHISE_Feature feature,
778 CHISE_Property property,
779 unsigned char *value)
781 if (property == NULL)
783 if (chise_property_setup_db (property, 1))
785 return chise_attribute_table_put (property->db, feature->name, value);
789 chise_feature_load_property_value (CHISE_Feature feature,
790 CHISE_Property_Table *table,
791 CHISE_Value *valdatum)
793 if (chise_property_setup_db (table, 0))
795 return chise_attribute_table_get (table->db, feature->name, valdatum);
799 chise_feature_gets_property_value (CHISE_Feature feature,
800 CHISE_Property_Table *table,
801 unsigned char *buf, size_t size)
803 CHISE_Value valdatum;
806 if (chise_property_setup_db (table, 0))
808 status = chise_attribute_table_get (table->db,
809 feature->name, &valdatum);
812 if (size < valdatum.size)
814 strncpy (buf, valdatum.data, valdatum.size);
815 buf[valdatum.size] = '\0';
820 CHISE_Attribute_Table*
821 CHISE_Attribute_Table_open (const unsigned char *db_dir,
822 const char *category,
823 const char *key_type, const char *name,
825 u_int32_t accessmask, int modemask)
829 int len, name_len, i;
831 char *db_file_name, *sp;
834 status = db_create (&dbase, NULL, 0);
838 if ( (accessmask & DB_CREATE) && stat (db_dir, &statbuf) )
839 mkdir (db_dir, modemask);
841 len = strlen (db_dir);
842 name_len = strlen (name);
843 size = len + strlen (category) + strlen (key_type) + name_len * 3 + 5;
844 db_file_name = alloca (size);
845 strcpy (db_file_name, db_dir);
846 if (db_file_name[len - 1] != '/')
848 db_file_name[len++] = '/';
849 db_file_name[len] = '\0';
852 strcat (db_file_name, category);
853 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
854 mkdir (db_file_name, modemask);
855 strcat (db_file_name, "/");
857 strcat (db_file_name, key_type);
858 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
859 mkdir (db_file_name, modemask);
860 strcat (db_file_name, "/");
862 /* strcat (db_file_name, name); */
863 sp = &db_file_name[strlen (db_file_name)];
864 for (i = 0; i < name_len; i++)
868 if ( (c == '/') || (c == '%') )
870 sprintf (sp, "%%%02X", c);
877 #if DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)
878 status = dbase->open (dbase, db_file_name, NULL,
879 real_subtype, accessmask, modemask);
880 #else /* DB_VERSION >= 4.1 */
881 status = dbase->open (dbase, NULL, db_file_name, NULL,
883 accessmask /* | DB_AUTO_COMMIT */, modemask);
884 #endif /* DB_VERSION < 4.1 */
887 dbase->close (dbase, 0);
894 CHISE_Attribute_Table_close (CHISE_Attribute_Table *db)
905 chise_attribute_table_get (CHISE_Attribute_Table *db,
906 char *key, CHISE_Value *valdatum)
911 /* DB Version 2 requires DBT's to be zeroed before use. */
916 keydatum.size = strlen (key);
918 status = db->get (db, NULL, &keydatum, valdatum, 0);
923 chise_attribute_table_put (CHISE_Attribute_Table *db,
924 char *key, unsigned char *value)
926 DBT keydatum, valdatum;
929 /* DB Version 2 requires DBT's to be zeroed before use. */
934 keydatum.size = strlen (key);
936 valdatum.data = value;
937 valdatum.size = strlen (value);
939 status = db->put (db, NULL, &keydatum, &valdatum, 0);
944 chise_char_id_parse_c_string (unsigned char *str, size_t len)
948 if ( (len >= 2) && (str[i++] == '?') )
950 unsigned char c = str[i++];
967 return c & (0x80 | 0x1F);
1001 if (counter + 2 <= len)
1005 for (j = 0; j < counter; j++)
1006 cid = (cid << 6) | (str[j + i] & 0x3F);
1014 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
1026 else if (cid == '\n')
1033 else if (cid == '\r')
1040 else if (cid == 0x1C)
1049 else if (cid <= 0x1F)
1053 dest[i++] = '@' + cid;
1057 else if ( (cid == ' ') || (cid == '"') ||
1058 (cid == '#') || (cid == '\'') ||
1059 (cid == '(') || (cid == ')') ||
1060 (cid == ',') || (cid == '.') ||
1061 (cid == ';') || (cid == '?') ||
1062 (cid == '[') || (cid == '\\') ||
1063 (cid == ']') || (cid == '`') )
1070 else if (cid <= 0x7E)
1076 else if (cid == 0x7F)
1084 else if (cid <= 0x9F)
1088 dest[i++] = ((cid + '@') >> 6) | 0xC0;
1089 dest[i++] = ((cid + '@') & 0x3F) | 0x80;
1093 else if (cid <= 0x7FF)
1095 dest[i++] = (cid >> 6) | 0xC0;
1096 dest[i++] = (cid & 0x3F) | 0x80;
1100 else if (cid <= 0xFFFF)
1102 dest[i++] = (cid >> 12) | 0xE0;
1103 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
1104 dest[i++]= (cid & 0x3F) | 0x80;
1108 else if (cid <= 0x1FFFFF)
1110 dest[i++]= (cid >> 18) | 0xF0;
1111 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
1112 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
1113 dest[i++]= (cid & 0x3F) | 0x80;
1117 else if (cid <= 0x3FFFFFF)
1119 dest[i++]= (cid >> 24) | 0xF8;
1120 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
1121 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
1122 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
1123 dest[i++]= (cid & 0x3F) | 0x80;
1129 dest[i++]= (cid >> 30) | 0xFC;
1130 dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
1131 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
1132 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
1133 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
1134 dest[i++]= (cid & 0x3F) | 0x80;