1 /* Copyright (C) 2003 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);
46 typedef DB CHISE_Attribute_Table;
48 CHISE_Attribute_Table*
49 CHISE_Attribute_Table_open (const unsigned char *db_dir,
51 const char *key_type, const char *name,
53 u_int32_t accessmask, int modemask);
55 int CHISE_Attribute_Table_close (CHISE_Attribute_Table *db);
57 int chise_attribute_table_get (CHISE_Attribute_Table *db,
58 char *key, CHISE_Value *valdatum);
60 int chise_attribute_table_put (CHISE_Attribute_Table *db,
61 char *key, unsigned char *value);
64 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
67 chise_char_id_parse_c_string (unsigned char *str, size_t len);
70 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len);
76 unsigned char *location;
77 CHISE_NAME_TABLE* feature_names;
78 CHISE_NAME_TABLE* ccs_names;
84 CHISE_DS_open (CHISE_DS_Type type, const unsigned char *location,
85 int subtype, int modemask)
87 CHISE_DS *ds = (CHISE_DS*)malloc (sizeof (CHISE_DS));
88 size_t len = strlen (location);
94 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
95 ds->modemask = modemask;
96 ds->location = (unsigned char*)malloc (len + 1);
97 if (ds->location == NULL)
102 strcpy (ds->location, location);
104 ds->feature_names = chise_make_name_table ();
105 if (ds->feature_names == NULL)
111 ds->ccs_names = chise_make_name_table ();
112 if (ds->ccs_names == NULL)
114 free (ds->feature_names);
122 CHISE_DS_close (CHISE_DS *ds)
124 if (ds->location != NULL)
126 if (ds->feature_names != NULL)
127 free (ds->feature_names);
128 if (ds->ccs_names != NULL)
129 free (ds->ccs_names);
135 chise_ds_get_feature (CHISE_DS *ds, const unsigned char *feature)
137 CHISE_Feature_Table* ft;
139 ft = chise_name_table_get (ds->feature_names, feature);
143 ft = chise_ds_open_feature_table (ds, feature);
147 if (chise_name_table_put (ds->feature_names, feature, ft))
156 chise_ds_get_ccs (CHISE_DS *ds, const unsigned char *ccs)
160 ct = chise_name_table_get (ds->ccs_names, ccs);
164 ct = chise_ds_open_ccs_table (ds, ccs);
168 if (chise_name_table_put (ds->ccs_names, ccs, ct))
170 chise_ccst_close (ct);
177 chise_ds_foreach_char_feature_name (CHISE_DS *ds,
178 int (*func) (CHISE_DS *ds,
179 unsigned char *name))
182 = alloca (strlen (ds->location) + sizeof ("/character/feature") + 1);
186 strcpy (dname, ds->location);
187 strcat (dname, "/character/feature");
189 if ( (dir = opendir (dname)) == NULL)
192 while ( (de = readdir (dir)) != NULL )
194 if ( (strcmp (de->d_name, ".") != 0) &&
195 (strcmp (de->d_name, "..") != 0) )
197 int i, need_to_decode = 0;
202 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
213 name = (unsigned char *) alloca (i);
217 while ( (ch = *cp++) != '\0')
233 if ( ('0' <= ch) && (ch <= '9') )
234 hex[index++] = ch - '0';
235 else if ( ('A' <= ch) && (ch <= 'F') )
236 hex[index++] = ch - 'A' + 10;
237 else if ( ('a' <= ch) && (ch <= 'f') )
238 hex[index++] = ch - 'a' + 10;
250 *np++ = (hex[0] << 4) | hex[1];
264 return closedir (dir);
267 return closedir (dir);
270 struct CHISE_Feature_Table
274 CHISE_Attribute_Table *db;
279 chise_ds_open_feature_table (CHISE_DS *ds, const char *feature)
281 CHISE_Feature_Table* table;
282 size_t len = strlen (feature);
287 table = (CHISE_Feature_Table*)malloc (sizeof (CHISE_Feature_Table));
294 table->name = (unsigned char*)malloc (len + 1);
295 if (table->name == NULL)
300 strcpy (table->name, feature);
305 chise_ft_close (CHISE_Feature_Table *table)
312 if (table->db == NULL)
315 status = CHISE_Attribute_Table_close (table->db);
317 if (table->name == NULL)
329 chise_feature_setup_db (CHISE_Feature feature, int writable)
338 if ((feature->access & DB_CREATE) == 0)
340 if (feature->db != NULL)
342 CHISE_Attribute_Table_close (feature->db);
352 if (feature->db == NULL)
354 CHISE_DS *ds = feature->ds;
357 = CHISE_Attribute_Table_open (ds->location, "character",
358 "feature", feature->name,
359 ds->subtype, access, ds->modemask);
360 if (feature->db == NULL)
362 feature->access = access;
368 chise_feature_sync (CHISE_Feature feature)
372 if (feature->db == NULL)
375 status = CHISE_Attribute_Table_close (feature->db);
382 chise_char_set_feature_value (CHISE_Char_ID cid,
383 CHISE_Feature feature,
384 unsigned char *value)
386 unsigned char key_buf[8];
390 if (chise_feature_setup_db (feature, 1))
392 chise_format_char_id (cid, key_buf, 8);
393 return chise_attribute_table_put (feature->db, key_buf, value);
397 chise_char_load_feature_value (CHISE_Char_ID cid,
398 CHISE_Feature_Table *table,
399 CHISE_Value *valdatum)
401 unsigned char key_buf[8];
403 if (chise_feature_setup_db (table, 0))
405 chise_format_char_id (cid, key_buf, 8);
406 return chise_attribute_table_get (table->db, key_buf, valdatum);
410 chise_char_gets_feature_value (CHISE_Char_ID cid,
411 CHISE_Feature_Table *table,
412 unsigned char *buf, size_t size)
414 CHISE_Value valdatum;
415 unsigned char key_buf[8];
418 if (chise_feature_setup_db (table, 0))
420 chise_format_char_id (cid, key_buf, 8);
421 status = chise_attribute_table_get (table->db,
425 if (size < valdatum.size)
427 strncpy (buf, valdatum.data, valdatum.size);
428 buf[valdatum.size] = '\0';
433 chise_feature_foreach_char_with_value (CHISE_Feature feature,
434 int (*func) (CHISE_Char_ID cid,
435 CHISE_Feature feature,
436 CHISE_Value *valdatum))
438 DBT keydatum, valdatum;
442 if (chise_feature_setup_db (feature, 0))
447 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
448 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST);
450 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT))
452 unsigned char *key_str = (unsigned char *)keydatum.data;
453 int key_len = strnlen (key_str, keydatum.size);
454 CHISE_Char_ID key = chise_char_id_parse_c_string (key_str, key_len);
455 int ret = func (key, feature, &valdatum);
460 dbcp->c_close (dbcp);
465 struct CHISE_CCS_Table
469 CHISE_Attribute_Table *db;
474 chise_ds_open_ccs_table (CHISE_DS *ds, const char *ccs)
476 CHISE_CCS_Table* table;
477 size_t len = strlen (ccs);
482 table = (CHISE_CCS_Table*)malloc (sizeof (CHISE_CCS_Table));
489 table->name = (unsigned char*)malloc (len + 1);
490 if (table->name == NULL)
495 strcpy (table->name, ccs);
500 chise_ccst_close (CHISE_CCS_Table *table)
507 if (table->db == NULL)
510 status = CHISE_Attribute_Table_close (table->db);
512 if (table->name == NULL)
524 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
533 if ((ccs->access & DB_CREATE) == 0)
537 CHISE_Attribute_Table_close (ccs->db);
549 CHISE_DS *ds = ccs->ds;
552 = CHISE_Attribute_Table_open (ds->location, "character",
553 "by_feature", ccs->name,
554 ds->subtype, access, ds->modemask);
557 ccs->access = access;
563 chise_ccs_sync (CHISE_CCS ccs)
570 status = CHISE_Attribute_Table_close (ccs->db);
577 chise_ccs_decode (CHISE_CCS ccs, int code_point)
579 CHISE_Value valdatum;
586 if (chise_ccs_setup_db (ccs, 0))
589 sprintf(key_buf, "%d", code_point);
590 status = chise_attribute_table_get (ccs->db, key_buf, &valdatum);
594 = (unsigned char *)chise_value_data (&valdatum);
595 int len = strnlen (str, chise_value_size (&valdatum));
597 return chise_char_id_parse_c_string (str, len);
603 chise_ccs_set_decoded_char (CHISE_CCS ccs,
604 int code_point, CHISE_Char_ID cid)
606 char key_buf[16], val_buf[8];
611 if (chise_ccs_setup_db (ccs, 1))
614 sprintf(key_buf, "%d", code_point);
615 chise_format_char_id (cid, val_buf, 8);
616 return chise_attribute_table_put (ccs->db, key_buf, val_buf);
620 CHISE_Attribute_Table*
621 CHISE_Attribute_Table_open (const unsigned char *db_dir,
622 const char *category,
623 const char *key_type, const char *name,
625 u_int32_t accessmask, int modemask)
629 int len, name_len, i;
631 char *db_file_name, *sp;
634 status = db_create (&dbase, NULL, 0);
638 if ( (accessmask & DB_CREATE) && stat (db_dir, &statbuf) )
639 mkdir (db_dir, modemask);
641 len = strlen (db_dir);
642 name_len = strlen (name);
643 size = len + strlen (category) + strlen (key_type) + name_len * 3 + 5;
644 db_file_name = alloca (size);
645 strcpy (db_file_name, db_dir);
646 if (db_file_name[len - 1] != '/')
648 db_file_name[len++] = '/';
649 db_file_name[len] = '\0';
652 strcat (db_file_name, category);
653 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
654 mkdir (db_file_name, modemask);
655 strcat (db_file_name, "/");
657 strcat (db_file_name, key_type);
658 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
659 mkdir (db_file_name, modemask);
660 strcat (db_file_name, "/");
662 /* strcat (db_file_name, name); */
663 sp = &db_file_name[strlen (db_file_name)];
664 for (i = 0; i < name_len; i++)
668 if ( (c == '/') || (c == '%') )
670 sprintf (sp, "%%%02X", c);
677 #if DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)
678 status = dbase->open (dbase, db_file_name, NULL,
679 real_subtype, accessmask, modemask);
680 #else /* DB_VERSION >= 4.1 */
681 status = dbase->open (dbase, NULL, db_file_name, NULL,
683 accessmask /* | DB_AUTO_COMMIT */, modemask);
684 #endif /* DB_VERSION < 4.1 */
687 dbase->close (dbase, 0);
694 CHISE_Attribute_Table_close (CHISE_Attribute_Table *db)
705 chise_attribute_table_get (CHISE_Attribute_Table *db,
706 char *key, CHISE_Value *valdatum)
711 /* DB Version 2 requires DBT's to be zeroed before use. */
716 keydatum.size = strlen (key);
718 status = db->get (db, NULL, &keydatum, valdatum, 0);
723 chise_attribute_table_put (CHISE_Attribute_Table *db,
724 char *key, unsigned char *value)
726 DBT keydatum, valdatum;
729 /* DB Version 2 requires DBT's to be zeroed before use. */
734 keydatum.size = strlen (key);
736 valdatum.data = value;
737 valdatum.size = strlen (value);
739 status = db->put (db, NULL, &keydatum, &valdatum, 0);
744 chise_char_id_parse_c_string (unsigned char *str, size_t len)
748 if ( (len >= 2) && (str[i++] == '?') )
750 unsigned char c = str[i++];
767 return c & (0x80 | 0x1F);
801 if (counter + 2 <= len)
805 for (j = 0; j < counter; j++)
806 cid = (cid << 6) | (str[j + i] & 0x3F);
814 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
826 else if (cid == '\n')
833 else if (cid == '\r')
840 else if (cid == 0x1C)
849 else if (cid <= 0x1F)
853 dest[i++] = '@' + cid;
857 else if ( (cid == ' ') || (cid == '"') ||
858 (cid == '#') || (cid == '\'') ||
859 (cid == '(') || (cid == ')') ||
860 (cid == ',') || (cid == '.') ||
861 (cid == ';') || (cid == '?') ||
862 (cid == '[') || (cid == '\\') ||
863 (cid == ']') || (cid == '`') )
870 else if (cid <= 0x7E)
876 else if (cid == 0x7F)
884 else if (cid <= 0x9F)
888 dest[i++] = ((cid + '@') >> 6) | 0xC0;
889 dest[i++] = ((cid + '@') & 0x3F) | 0x80;
893 else if (cid <= 0x7FF)
895 dest[i++] = (cid >> 6) | 0xC0;
896 dest[i++] = (cid & 0x3F) | 0x80;
900 else if (cid <= 0xFFFF)
902 dest[i++] = (cid >> 12) | 0xE0;
903 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
904 dest[i++]= (cid & 0x3F) | 0x80;
908 else if (cid <= 0x1FFFFF)
910 dest[i++]= (cid >> 18) | 0xF0;
911 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
912 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
913 dest[i++]= (cid & 0x3F) | 0x80;
917 else if (cid <= 0x3FFFFFF)
919 dest[i++]= (cid >> 24) | 0xF8;
920 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
921 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
922 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
923 dest[i++]= (cid & 0x3F) | 0x80;
929 dest[i++]= (cid >> 30) | 0xFC;
930 dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
931 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
932 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
933 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
934 dest[i++]= (cid & 0x3F) | 0x80;