11 #include "chise-name.h"
13 const unsigned char chise_db_dir[] = CHISE_DB_DIR;
14 const unsigned char chise_system_db_dir[] = CHISE_SI_DB_DIR;
17 chise_ds_open_feature_table (CHISE_DS *ds, const char *feature);
19 int chise_ft_close (CHISE_Feature_Table *table);
23 chise_ds_open_ccs_table (CHISE_DS *ds, const char *ccs);
25 int chise_ccst_close (CHISE_CCS_Table *table);
28 typedef DB CHISE_Attribute_Table;
30 CHISE_Attribute_Table*
31 CHISE_Attribute_Table_open (const unsigned char *db_dir,
33 const char *key_type, const char *name,
35 u_int32_t accessmask, int modemask);
37 int CHISE_Attribute_Table_close (CHISE_Attribute_Table *db);
39 int chise_attribute_table_get (CHISE_Attribute_Table *db,
40 char *key, CHISE_Value *valdatum);
42 int chise_attribute_table_put (CHISE_Attribute_Table *db,
43 char *key, unsigned char *value);
46 #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue)))
49 chise_char_id_parse_c_string (unsigned char *str, size_t len);
52 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len);
58 unsigned char *location;
59 CHISE_NAME_TABLE* feature_names;
60 CHISE_NAME_TABLE* ccs_names;
66 CHISE_DS_open (CHISE_DS_Type type, const unsigned char *location,
67 int subtype, int modemask)
69 CHISE_DS *ds = (CHISE_DS*)malloc (sizeof (CHISE_DS));
70 size_t len = strlen (location);
76 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
77 ds->modemask = modemask;
78 ds->location = (unsigned char*)malloc (len + 1);
79 if (ds->location == NULL)
84 strcpy (ds->location, location);
86 ds->feature_names = chise_make_name_table ();
87 if (ds->feature_names == NULL)
93 ds->ccs_names = chise_make_name_table ();
94 if (ds->ccs_names == NULL)
96 free (ds->feature_names);
104 CHISE_DS_close (CHISE_DS *ds)
106 if (ds->location != NULL)
108 if (ds->feature_names != NULL)
109 free (ds->feature_names);
110 if (ds->ccs_names != NULL)
111 free (ds->ccs_names);
117 chise_ds_get_feature (CHISE_DS *ds, const unsigned char *feature)
119 CHISE_Feature_Table* ft;
121 ft = chise_name_table_get (ds->feature_names, feature);
125 ft = chise_ds_open_feature_table (ds, feature);
129 if (chise_name_table_put (ds->feature_names, feature, ft))
138 chise_ds_get_ccs (CHISE_DS *ds, const unsigned char *ccs)
142 ct = chise_name_table_get (ds->ccs_names, ccs);
146 ct = chise_ds_open_ccs_table (ds, ccs);
150 if (chise_name_table_put (ds->ccs_names, ccs, ct))
152 chise_ccst_close (ct);
159 chise_ds_foreach_char_feature_name (CHISE_DS *ds,
160 int (*func) (CHISE_DS *ds,
161 unsigned char *name))
164 = alloca (strlen (ds->location) + sizeof ("/character/feature") + 1);
168 strcpy (dname, ds->location);
169 strcat (dname, "/character/feature");
171 if ( (dir = opendir (dname)) == NULL)
174 while ( (de = readdir (dir)) != NULL )
176 if ( (strcmp (de->d_name, ".") != 0) &&
177 (strcmp (de->d_name, "..") != 0) )
179 int i, need_to_decode = 0;
184 for (cp = de->d_name, i = 0; *cp != '\0'; i++)
195 name = (unsigned char *) alloca (i);
199 while ( (ch = *cp++) != '\0')
215 if ( ('0' <= ch) && (ch <= '9') )
216 hex[index++] = ch - '0';
217 else if ( ('A' <= ch) && (ch <= 'F') )
218 hex[index++] = ch - 'A' + 10;
219 else if ( ('a' <= ch) && (ch <= 'f') )
220 hex[index++] = ch - 'a' + 10;
232 *np++ = (hex[0] << 4) | hex[1];
246 return closedir (dir);
249 return closedir (dir);
252 struct CHISE_Feature_Table
256 CHISE_Attribute_Table *db;
261 chise_ds_open_feature_table (CHISE_DS *ds, const char *feature)
263 CHISE_Feature_Table* table;
264 size_t len = strlen (feature);
269 table = (CHISE_Feature_Table*)malloc (sizeof (CHISE_Feature_Table));
276 table->name = (unsigned char*)malloc (len + 1);
277 if (table->name == NULL)
282 strcpy (table->name, feature);
287 chise_ft_close (CHISE_Feature_Table *table)
294 if (table->db == NULL)
297 status = CHISE_Attribute_Table_close (table->db);
299 if (table->name == NULL)
311 chise_feature_setup_db (CHISE_Feature feature, int writable)
320 if ((feature->access & DB_CREATE) == 0)
322 if (feature->db != NULL)
324 CHISE_Attribute_Table_close (feature->db);
334 if (feature->db == NULL)
336 CHISE_DS *ds = feature->ds;
339 = CHISE_Attribute_Table_open (ds->location, "character",
340 "feature", feature->name,
341 ds->subtype, access, ds->modemask);
342 if (feature->db == NULL)
344 feature->access = access;
350 chise_feature_sync (CHISE_Feature feature)
354 if (feature->db == NULL)
357 status = CHISE_Attribute_Table_close (feature->db);
364 chise_char_set_feature_value (CHISE_Char_ID cid,
365 CHISE_Feature feature,
366 unsigned char *value)
368 unsigned char key_buf[8];
372 if (chise_feature_setup_db (feature, 1))
374 chise_format_char_id (cid, key_buf, 8);
375 return chise_attribute_table_put (feature->db, key_buf, value);
379 chise_char_load_feature_value (CHISE_Char_ID cid,
380 CHISE_Feature_Table *table,
381 CHISE_Value *valdatum)
383 unsigned char key_buf[8];
385 if (chise_feature_setup_db (table, 0))
387 chise_format_char_id (cid, key_buf, 8);
388 return chise_attribute_table_get (table->db, key_buf, valdatum);
392 chise_char_gets_feature_value (CHISE_Char_ID cid,
393 CHISE_Feature_Table *table,
394 unsigned char *buf, size_t size)
396 CHISE_Value valdatum;
397 unsigned char key_buf[8];
400 if (chise_feature_setup_db (table, 0))
402 chise_format_char_id (cid, key_buf, 8);
403 status = chise_attribute_table_get (table->db,
407 if (size < valdatum.size)
409 strncpy (buf, valdatum.data, valdatum.size);
410 buf[valdatum.size] = '\0';
415 chise_feature_foreach_char_with_value (CHISE_Feature feature,
416 int (*func) (CHISE_Char_ID cid,
417 CHISE_Feature feature,
418 CHISE_Value *valdatum))
420 DBT keydatum, valdatum;
424 if (chise_feature_setup_db (feature, 0))
429 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
430 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST);
432 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT))
434 unsigned char *key_str = (unsigned char *)keydatum.data;
435 int key_len = strnlen (key_str, keydatum.size);
436 CHISE_Char_ID key = chise_char_id_parse_c_string (key_str, key_len);
437 int ret = func (key, feature, &valdatum);
442 dbcp->c_close (dbcp);
447 struct CHISE_CCS_Table
451 CHISE_Attribute_Table *db;
456 chise_ds_open_ccs_table (CHISE_DS *ds, const char *ccs)
458 CHISE_CCS_Table* table;
459 size_t len = strlen (ccs);
464 table = (CHISE_CCS_Table*)malloc (sizeof (CHISE_CCS_Table));
471 table->name = (unsigned char*)malloc (len + 1);
472 if (table->name == NULL)
477 strcpy (table->name, ccs);
482 chise_ccst_close (CHISE_CCS_Table *table)
489 if (table->db == NULL)
492 status = CHISE_Attribute_Table_close (table->db);
494 if (table->name == NULL)
506 chise_ccs_setup_db (CHISE_CCS ccs, int writable)
515 if ((ccs->access & DB_CREATE) == 0)
519 CHISE_Attribute_Table_close (ccs->db);
531 CHISE_DS *ds = ccs->ds;
534 = CHISE_Attribute_Table_open (ds->location, "character",
535 "by_feature", ccs->name,
536 ds->subtype, access, ds->modemask);
539 ccs->access = access;
545 chise_ccs_sync (CHISE_CCS ccs)
552 status = CHISE_Attribute_Table_close (ccs->db);
559 chise_ccs_decode (CHISE_CCS ccs, int code_point)
561 CHISE_Value valdatum;
568 if (chise_ccs_setup_db (ccs, 0))
571 sprintf(key_buf, "%d", code_point);
572 status = chise_attribute_table_get (ccs->db, key_buf, &valdatum);
576 = (unsigned char *)chise_value_data (&valdatum);
577 int len = strnlen (str, chise_value_size (&valdatum));
579 return chise_char_id_parse_c_string (str, len);
585 chise_ccs_set_decoded_char (CHISE_CCS ccs,
586 int code_point, CHISE_Char_ID cid)
588 char key_buf[16], val_buf[8];
593 if (chise_ccs_setup_db (ccs, 1))
596 sprintf(key_buf, "%d", code_point);
597 chise_format_char_id (cid, val_buf, 8);
598 return chise_attribute_table_put (ccs->db, key_buf, val_buf);
602 CHISE_Attribute_Table*
603 CHISE_Attribute_Table_open (const unsigned char *db_dir,
604 const char *category,
605 const char *key_type, const char *name,
607 u_int32_t accessmask, int modemask)
611 int len, name_len, i;
613 char *db_file_name, *sp;
616 status = db_create (&dbase, NULL, 0);
620 if ( (accessmask & DB_CREATE) && stat (db_dir, &statbuf) )
621 mkdir (db_dir, modemask);
623 len = strlen (db_dir);
624 name_len = strlen (name);
625 size = len + strlen (category) + strlen (key_type) + name_len * 3 + 5;
626 db_file_name = alloca (size);
627 strcpy (db_file_name, db_dir);
628 if (db_file_name[len - 1] != '/')
630 db_file_name[len++] = '/';
631 db_file_name[len] = '\0';
634 strcat (db_file_name, category);
635 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
636 mkdir (db_file_name, modemask);
637 strcat (db_file_name, "/");
639 strcat (db_file_name, key_type);
640 if ( (accessmask & DB_CREATE) && stat (db_file_name, &statbuf) )
641 mkdir (db_file_name, modemask);
642 strcat (db_file_name, "/");
644 /* strcat (db_file_name, name); */
645 sp = &db_file_name[strlen (db_file_name)];
646 for (i = 0; i < name_len; i++)
650 if ( (c == '/') || (c == '%') )
652 sprintf (sp, "%%%02X", c);
659 #if DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)
660 status = dbase->open (dbase, db_file_name, NULL,
661 real_subtype, accessmask, modemask);
662 #else /* DB_VERSION >= 4.1 */
663 status = dbase->open (dbase, NULL, db_file_name, NULL,
665 accessmask /* | DB_AUTO_COMMIT */, modemask);
666 #endif /* DB_VERSION < 4.1 */
669 dbase->close (dbase, 0);
676 CHISE_Attribute_Table_close (CHISE_Attribute_Table *db)
687 chise_attribute_table_get (CHISE_Attribute_Table *db,
688 char *key, CHISE_Value *valdatum)
693 /* DB Version 2 requires DBT's to be zeroed before use. */
698 keydatum.size = strlen (key);
700 status = db->get (db, NULL, &keydatum, valdatum, 0);
705 chise_attribute_table_put (CHISE_Attribute_Table *db,
706 char *key, unsigned char *value)
708 DBT keydatum, valdatum;
711 /* DB Version 2 requires DBT's to be zeroed before use. */
716 keydatum.size = strlen (key);
718 valdatum.data = value;
719 valdatum.size = strlen (value);
721 status = db->put (db, NULL, &keydatum, &valdatum, 0);
726 chise_char_id_parse_c_string (unsigned char *str, size_t len)
730 if ( (len >= 2) && (str[i++] == '?') )
732 unsigned char c = str[i++];
749 return c & (0x80 | 0x1F);
783 if (counter + 2 <= len)
787 for (j = 0; j < counter; j++)
788 cid = (cid << 6) | (str[j + i] & 0x3F);
796 chise_format_char_id (CHISE_Char_ID cid, unsigned char *dest, size_t len)
808 else if (cid == '\n')
815 else if (cid == '\r')
822 else if (cid == 0x1C)
831 else if (cid <= 0x1F)
835 dest[i++] = '@' + cid;
839 else if ( (cid == ' ') || (cid == '"') ||
840 (cid == '#') || (cid == '\'') ||
841 (cid == '(') || (cid == ')') ||
842 (cid == ',') || (cid == '.') ||
843 (cid == ';') || (cid == '?') ||
844 (cid == '[') || (cid == '\\') ||
845 (cid == ']') || (cid == '`') )
852 else if (cid <= 0x7E)
858 else if (cid == 0x7F)
866 else if (cid <= 0x9F)
870 dest[i++] = ((cid + '@') >> 6) | 0xC0;
871 dest[i++] = ((cid + '@') & 0x3F) | 0x80;
875 else if (cid <= 0x7FF)
877 dest[i++] = (cid >> 6) | 0xC0;
878 dest[i++] = (cid & 0x3F) | 0x80;
882 else if (cid <= 0xFFFF)
884 dest[i++] = (cid >> 12) | 0xE0;
885 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
886 dest[i++]= (cid & 0x3F) | 0x80;
890 else if (cid <= 0x1FFFFF)
892 dest[i++]= (cid >> 18) | 0xF0;
893 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
894 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
895 dest[i++]= (cid & 0x3F) | 0x80;
899 else if (cid <= 0x3FFFFFF)
901 dest[i++]= (cid >> 24) | 0xF8;
902 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
903 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
904 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
905 dest[i++]= (cid & 0x3F) | 0x80;
911 dest[i++]= (cid >> 30) | 0xFC;
912 dest[i++]= ((cid >> 24) & 0x3F) | 0x80;
913 dest[i++]= ((cid >> 18) & 0x3F) | 0x80;
914 dest[i++]= ((cid >> 12) & 0x3F) | 0x80;
915 dest[i++]= ((cid >> 6) & 0x3F) | 0x80;
916 dest[i++]= (cid & 0x3F) | 0x80;