*** empty log message ***
[m17n/m17n-lib.git] / src / chartab.c
1 /* chartab.h -- character table module.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nChartable
25     @brief Chartable objects and API for them.
26
27     The m17n library supports enormous number of characters.  Thus, if
28     attributes of each character are to be stored in a simple array,
29     such an array would be impractically big.  The attributes usually
30     used, however, are often assigned only to a range of characters.
31     Even when all characters have attributes, characters of
32     consecutive character code tend to have the same attribute values.
33
34     The m17n library utilizes this tendency to store characters and
35     their attribute values efficiently in an object called @e
36     Chartable.  Although a chartable object is not a simple array,
37     application programs can handle a chartable as if it is an array.
38     Attribute values of a character can be obtained by accessing a
39     Chartable for the attribute with the character code of the
40     specified character.
41
42     A chartable is a managed object.  */
43
44 /***ja
45     @addtogroup m17nChartable Ê¸»ú¥Æ¡¼¥Ö¥ë
46
47     @brief Ê¸»ú¥Æ¡¼¥Ö¥ë¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
48
49     m17n ¥é¥¤¥Ö¥é¥ê¤¬°·¤¦Ê¸»ú¤Î¶õ´Ö¤Ï¹­Âç¤Ç¤¢¤ë¤¿¤á¡¢Ê¸»úËè¤Î¾ðÊó¤òñ½ã¤ÊÇÛÎó¤Ë³ÊǼ¤·¤è¤¦¤È¤¹¤ë¤È¡¢¤½¤ÎÇÛÎó¤ÏµðÂç¤Ë¤Ê¤ê¤¹¤®¡¢Èó¼ÂÍÑŪ¤Ç¤¢¤ë¡£
50     ¤·¤«¤·Ä̾ïɬÍפȤʤëʸ»ú¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤Ï¡¢¤¢¤ëÆÃÄê¤ÎÈϰϤÎʸ»ú¤Ë¤Î¤ßÉÕ¤¤¤Æ¤¤¤ë¤³¤È¤¬Â¿¤¤¡£
51     Á´Ê¸»ú¤Ë´Ø¤·¤Æ¾ðÊ󤬤¢¤ë¾ì¹ç¤Ë¤â¡¢Ï¢Â³¤·¤¿Ê¸»ú¥³¡¼¥É¤ò»ý¤Äʸ»ú¤ÏƱ¤¸¾ðÊó¤ò»ý¤Ä¤³¤È¤¬Â¿¤¤¡£
52
53     ¤³¤Î¤è¤¦¤Ê·¹¸þ¤òÍøÍѤ·¤Æʸ»ú¤È¤½¤ÎÉղþðÊó¤ò¸úΨŪ¤Ë³ÊǼ¤¹¤ë¤¿¤á¤Ë¡¢
54     m17n ¥é¥¤¥Ö¥é¥ê¤Ï @e Ê¸»ú¥Æ¡¼¥Ö¥ë (chartable) ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤òÍѤ¤¤ë¡£
55     Ê¸»ú¥Æ¡¼¥Ö¥ë¤ÏÇÛÎó¤Ç¤Ï¤Ê¤¤¤¬¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ïʸ»ú¥Æ¡¼¥Ö¥ë¤òÇÛÎó¤Î°ì¼ï¤È¤·¤Æ°·¤¦¤³¤È¤¬¤Ç¤­¤ë¡£
56     ¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤ÎÆÃÄê¤Î¾ðÊó¤Ï¡¢¤½¤Î¾ðÊó¤ò»ý¤Äʸ»ú¥Æ¡¼¥Ö¥ë¤ò¤½¤Îʸ»ú¤Î¥³¡¼¥É¤Ç°ú¤¯¤³¤È
57     ¤ÇÆÀ¤é¤ì¤ë¡£  
58
59     Ê¸»ú¥Æ¡¼¥Ö¥ë¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£ */
60
61 /*=*/
62 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
63 /*** @addtogroup m17nInternal
64      @{ */
65
66 #include <config.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <limits.h>
70 #include <ctype.h>
71 #include <stdio.h>
72
73 #include "m17n.h"
74 #include "m17n-misc.h"
75 #include "internal.h"
76 #include "symbol.h"
77
78 static M17NObjectArray chartable_table;
79
80 /*** Maximum depth of char-table.  */
81 #define CHAR_TAB_MAX_DEPTH 3
82
83 /** @name Define: Number of characters covered by char-table of each level.
84     @{ */
85
86 /** BITs for number of characters covered by char-table of each
87     level.  */
88 #if MCHAR_MAX < 0x400000
89
90 #define SUB_BITS_0      22      /* i.e. 0x400000 chars */
91 #define SUB_BITS_1      16      /* i.e. 0x10000 chars */
92 #define SUB_BITS_2      12      /* i.e. 0x1000 chars */
93 #define SUB_BITS_3      7       /* i.e. 0x80 chars */
94
95 #else  /* MCHAR_MAX >= 0x400000 */
96
97 #define SUB_BITS_0      31
98 #define SUB_BITS_1      24
99 #define SUB_BITS_2      16
100 #define SUB_BITS_3      8
101 #endif
102
103 /** @} */
104
105 /** How many characters a char-table covers at each level.  */
106 static const int chartab_chars[] =
107   { (1 << SUB_BITS_0),
108     (1 << SUB_BITS_1),
109     (1 << SUB_BITS_2),
110     (1 << SUB_BITS_3) };
111
112 /** How many slots a char-table has at each level.  */
113 static const int chartab_slots[] =
114   { (1 << (SUB_BITS_0 - SUB_BITS_1)),
115     (1 << (SUB_BITS_1 - SUB_BITS_2)),
116     (1 << (SUB_BITS_2 - SUB_BITS_3)),
117     (1 << SUB_BITS_3) };
118
119 /** Mask bits to obtain the valid bits from a character code for looking
120     up a char-table of each level.  */
121 static const int chartab_mask[] =
122   { (int) ((((unsigned) 1) << SUB_BITS_0) - 1),
123     (1 << SUB_BITS_1) - 1,
124     (1 << SUB_BITS_2) - 1,
125     (1 << SUB_BITS_3) - 1 };
126
127 /** Bit-shifting counts to obtain a valid index from a character code
128     for looking up a char-table of each level.  */
129 static const int chartab_shift[] =
130   { SUB_BITS_1, SUB_BITS_2, SUB_BITS_3, 0 };
131
132
133 /** Index for looking up character C in a char-table at DEPTH.  */
134 #define SUB_IDX(depth, c)       \
135   (((c) & chartab_mask[depth]) >> chartab_shift[depth])
136
137
138 /** Structure of sub char-table.  */
139 typedef struct MSubCharTable MSubCharTable;
140
141 struct MSubCharTable
142 {
143 #if SUB_BITS_0 > 24
144
145   /* The depth of the table; 0, 1, 2, or 3. */
146   int depth;
147
148   /* The minimum character covered by the table.  */
149   int min_char;
150
151 #else  /* SUB_BITS_0 <= 24 */
152
153   /* The value is ((<depth> << 24) | <min_char>).  */
154   int depth_min_char;
155
156 #endif  /* SUB_BITS_0 <= 24 */
157
158   /** The default value of characters covered by the table.  */
159   void *default_value;
160
161   /** For a table of bottom level, array of values.  For a non-bottom
162      table, array of sub char-tables.  It may be NULL if all
163      characters covered by the table has <default_value>.  */
164   union {
165     void **values;
166     MSubCharTable *tables;
167   } contents;
168 };
169
170 #if SUB_BITS_0 > 24
171 #define TABLE_DEPTH(table) ((table)->depth)
172 #define TABLE_MIN_CHAR(table) ((table)->min_char)
173 #define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
174   ((table)->depth = (DEPTH), (table)->min_char = (MIN_CHAR))
175 #else  /* SUB_BITS_0 <= 24 */
176 #define TABLE_DEPTH(table) ((table)->depth_min_char >> 24)
177 #define TABLE_MIN_CHAR(table) ((table)->depth_min_char & 0xFFFFFF)
178 #define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
179   ((table)->depth_min_char = ((DEPTH) << 24) | (MIN_CHAR))
180 #endif  /* SUB_BITS_0 <= 24 */
181
182 /** Structure of char-table.  */
183
184 struct MCharTable
185 {
186   /** Common header for a managed object.  */
187   M17NObject control;
188
189   /** Key of the table.  */
190   MSymbol key;
191
192   /** The minimum and maximum characters covered by the table.  */
193   int min_char, max_char;
194
195   MSubCharTable subtable;
196 };
197
198
199 \f
200
201 /* Local functions.  */
202
203 /** Allocate and initialize an array of sub-tables for sub char-table
204     TABLE.  It is assumed that TABLE_DEPTH (TABLE) <
205     CHAR_TAB_MAX_DEPTH.*/
206
207 static void
208 make_sub_tables (MSubCharTable *table, int managedp)
209 {
210   int depth = TABLE_DEPTH (table);
211   int min_char = TABLE_MIN_CHAR (table);
212   int slots = chartab_slots[depth];
213   int chars = chartab_chars[depth + 1];
214   MSubCharTable *tables;
215   int i;
216
217   MTABLE_MALLOC (tables, slots, MERROR_CHARTABLE);
218
219   for (i = 0; i < slots; i++, min_char += chars)
220     {
221       SET_DEPTH_MIN_CHAR (tables + i, depth + 1, min_char);
222       tables[i].default_value = table->default_value;
223       tables[i].contents.tables = NULL;
224     }
225   if (managedp && table->default_value)
226     M17N_OBJECT_REF_NTIMES (tables->default_value, slots);
227   table->contents.tables = tables;
228 }
229
230
231 /** Allocate and initialize an array of values for sub char-table
232     TABLE.  It is assumed that TABLE_DEPTH (TABLE) ==
233     CHAR_TAB_MAX_DEPTH.  */
234
235 static void
236 make_sub_values (MSubCharTable *table, int managedp)
237 {
238   int slots = chartab_slots[CHAR_TAB_MAX_DEPTH];
239   void **values;
240   int i;
241
242   MTABLE_MALLOC (values, slots, MERROR_CHARTABLE);
243
244   for (i = 0; i < slots; i++)
245     values[i] = table->default_value;
246   if (managedp && table->default_value)
247     M17N_OBJECT_REF_NTIMES (table->default_value, slots);
248   table->contents.values = values;
249 }
250
251
252 /** Free contents of sub char-table TABLE and the default value of
253     TABLE.  Free also the sub-tables recursively.  */
254
255 static void
256 free_sub_tables (MSubCharTable *table, int managedp)
257 {
258   int depth = TABLE_DEPTH (table);
259   int slots = chartab_slots[depth];
260
261   if (table->contents.tables)
262     {
263       if (depth < CHAR_TAB_MAX_DEPTH)
264         {
265           while (slots--)
266             free_sub_tables (table->contents.tables + slots, managedp);
267           free (table->contents.tables);
268         }
269       else
270         {
271           if (managedp)
272             while (slots--)
273               {
274                 if (table->contents.values[slots])
275                   M17N_OBJECT_UNREF (table->contents.values[slots]);
276               }
277           free (table->contents.values);
278         }
279       table->contents.tables = NULL;
280     }
281   if (managedp && table->default_value)
282     M17N_OBJECT_UNREF (table->default_value);
283 }
284
285
286 /** In sub char-table TABLE, set value VAL for characters of the range
287     FROM and TO. */
288
289 static void
290 set_chartable_range (MSubCharTable *table, int from, int to, void *val,
291                      int managedp)
292 {
293   int depth = TABLE_DEPTH (table);
294   int min_char = TABLE_MIN_CHAR (table);
295   int max_char = min_char + (chartab_chars[depth] - 1);
296   int i;
297
298   if (max_char < 0 || max_char > MCHAR_MAX)
299     max_char = MCHAR_MAX;
300
301   if (from < min_char)
302     from = min_char;
303   if (to > max_char)
304     to = max_char;
305
306   if (from == min_char && to == max_char)
307     {
308       free_sub_tables (table, managedp);
309       if (managedp && val)
310         M17N_OBJECT_REF (val);
311       table->default_value = val;
312       return;
313     }
314
315   if (depth < CHAR_TAB_MAX_DEPTH)
316     {
317       if (! table->contents.tables)
318         make_sub_tables (table, managedp);
319       i = SUB_IDX (depth, from);
320       table = table->contents.tables + i;
321       while (i < chartab_slots[depth] && TABLE_MIN_CHAR (table) <= to)
322         {
323           set_chartable_range (table, from, to, val, managedp);
324           table++, i++;
325         }
326     }
327   else
328     {
329       int idx_from = SUB_IDX (depth, from);
330       int idx_to = SUB_IDX (depth, to);
331
332       if (! table->contents.values)
333         make_sub_values (table, managedp);
334       for (i = idx_from; i <= idx_to; i++)
335         {
336           if (managedp && table->contents.values[i])
337             M17N_OBJECT_UNREF (table->contents.values[i]);
338           table->contents.values[i] = val;
339         }
340       if (managedp && val)
341         M17N_OBJECT_REF_NTIMES (val, (idx_to - idx_from + 1));
342     }
343 }
344
345
346 /** Lookup the sub char-table TABLE for the character C.  If NEXT_C is
347     not NULL, set *NEXT_C to the next interesting character to lookup
348     for.  If DEFAULT_P is zero, the next interesting character is what
349     possibly has the different value than C.  Otherwise, the next
350     interesting character is what possibly has the default value (if C
351     has a value deferent from the default value) or has a value
352     different from the default value (if C has the default value).  */
353
354 static void *
355 lookup_chartable (MSubCharTable *table, int c, int *next_c, int default_p)
356 {
357   int depth = TABLE_DEPTH (table);
358   void *val;
359   void *default_value = table->default_value;
360   int idx;
361
362   while (1)
363     {
364       if (! table->contents.tables)
365         {
366           if (next_c)
367             *next_c = TABLE_MIN_CHAR (table) + chartab_chars[depth];
368           return table->default_value;
369         }
370       if (depth == CHAR_TAB_MAX_DEPTH)
371         break;
372       table = table->contents.tables + SUB_IDX (depth, c);
373       depth++;
374     }
375
376   idx = SUB_IDX (depth, c);
377   val = table->contents.values[idx];
378
379   if (next_c)
380     {
381       int max_char = TABLE_MIN_CHAR (table) + (chartab_chars[depth] - 1);
382
383       if (max_char < 0 || max_char > MCHAR_MAX)
384         max_char = MCHAR_MAX;
385       if (default_p && val != default_value)
386         {
387           do { c++, idx++; }
388           while (c >= 0 && c <= max_char
389                  && table->contents.values[idx] != default_value);
390         }
391       else
392         {
393           do { c++, idx++; }
394           while (c >= 0 && c <= max_char
395                  && table->contents.values[idx] == val);
396         }
397       *next_c = c;
398     }
399   return val;
400 }
401
402 /** Call FUNC for characters in sub char-table TABLE.  Ignore such
403     characters that has a value IGNORE.  FUNC is called with four
404     arguments; FROM, TO, VAL, and ARG (same as FUNC_ARG).  If
405     DEFAULT_P is zero, FROM and TO are range of characters that has
406     the same value VAL.  Otherwise, FROM and TO are range of
407     characters that has the different value than the default value of
408     TABLE.  */
409
410 static void
411 map_chartable (MSubCharTable *table, void *ignore, int default_p,
412                 void (*func) (int, int, void *, void *),
413                 void *func_arg)
414 {
415   void *current;
416   int from = 0;
417   int c, next_c;
418
419   current = lookup_chartable (table, 0, &next_c, default_p);
420   c = next_c;
421   while (c >= 0 && c <= MCHAR_MAX)
422     {
423       void *next = lookup_chartable (table, c, &next_c, default_p);
424
425       if (current != next)
426         {
427           if (current != ignore)
428             (*func) (from, c - 1, current, func_arg);
429           current = next;
430           from = c;
431         }
432       c = next_c;
433     }
434   if (from <= MCHAR_MAX && current != ignore)
435     (*func) (from, MCHAR_MAX, current, func_arg);
436 }
437
438
439 /* Return the smallest character whose value is not DEFAULT_VALUE in
440    TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
441    -1.  */
442
443 static int
444 chartab_min_non_default_char (MSubCharTable *table, void *default_value)
445 {
446   int depth = TABLE_DEPTH (table);
447   int slots;
448   int i, c;
449
450   if (!table->contents.tables)
451     return (default_value == table->default_value
452             ? -1 : TABLE_MIN_CHAR (table));
453
454   slots = chartab_slots[depth];
455
456   if (depth == CHAR_TAB_MAX_DEPTH)
457     {
458       for (i = 0; i < slots; i++)
459         if (table->contents.values[i] != default_value)
460           return (TABLE_MIN_CHAR (table) + i);
461     }
462   else
463     {
464       for (i = 0; i < slots; i++)
465         if ((c = chartab_min_non_default_char (table->contents.tables + i,
466                                                default_value))
467             >= 0)
468           return c;
469     }
470   return -1;
471 }
472
473
474 /* Return the largest character whose value is not DEFAULT_VALUE in
475    TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
476    -1.  */
477
478 static int
479 chartab_max_non_default_char (MSubCharTable *table, void *default_value)
480 {
481   int depth = TABLE_DEPTH (table);
482   int slots;
483   int i, c;
484
485   if (!table->contents.tables)
486     return (default_value == table->default_value
487             ? -1 : TABLE_MIN_CHAR (table) + chartab_chars[depth] - 1);
488
489   slots = chartab_slots[depth];
490
491   if (depth == CHAR_TAB_MAX_DEPTH)
492     {
493       for (i = slots - 1; i >= 0; i--)
494         if (table->contents.values[i] != default_value)
495           return (TABLE_MIN_CHAR (table) + i);
496     }
497   else
498     {
499       for (i = slots - 1; i >= 0; i--)
500         if ((c = chartab_max_non_default_char (table->contents.tables + i,
501                                                default_value))
502             >= 0)
503           return c;
504     }
505   return -1;
506 }
507
508 static void
509 free_chartable (void *object)
510 {
511   MCharTable *table = (MCharTable *) object;
512   int managedp = table->key != Mnil && table->key->managing_key;
513
514   if (table->subtable.contents.tables)
515     {
516       int i;
517
518       for (i = 0; i < chartab_slots[0]; i++)
519         free_sub_tables (table->subtable.contents.tables + i, managedp);
520       free (table->subtable.contents.tables);
521       if (managedp && table->subtable.default_value)
522         M17N_OBJECT_UNREF (table->subtable.default_value);
523     }
524   M17N_OBJECT_UNREGISTER (chartable_table, table);
525   free (object);
526 }
527
528 #include <stdio.h>
529
530 /* Support function of mdebug_dump_chartab.  */
531
532 static void
533 dump_sub_chartab (MSubCharTable *table, void *default_value,
534                   MSymbol key, int indent)
535 {
536   int depth = TABLE_DEPTH (table);
537   int min_char = TABLE_MIN_CHAR (table);
538   int max_char = min_char + (chartab_chars[depth] - 1);
539   char *prefix = (char *) alloca (indent + 1);
540   int i;
541
542   if (max_char < 0 || max_char > MCHAR_MAX)
543     max_char = MCHAR_MAX;
544
545   memset (prefix, 32, indent);
546   prefix[indent] = 0;
547
548   if (! table->contents.tables && table->default_value == default_value)
549     return;
550   fprintf (mdebug__output, "\n%s(sub%d (U+%04X U+%04X) ",
551            prefix, depth, min_char, max_char);
552   if (key == Msymbol)
553     {
554       if (table->default_value)
555         fprintf (mdebug__output, "(default %s)",
556                  ((MSymbol) table->default_value)->name);
557       else
558         fprintf (mdebug__output, "(default nil)");
559     }
560   else
561     fprintf (mdebug__output, "(default #x%X)", (unsigned) table->default_value);
562
563   default_value = table->default_value;
564   if (table->contents.tables)
565     {
566       if (depth < CHAR_TAB_MAX_DEPTH)
567         for (i = 0; i < chartab_slots[depth]; i++)
568           dump_sub_chartab (table->contents.tables + i, default_value,
569                             key, indent  + 2);
570       else
571         for (i = 0; i < chartab_slots[depth]; i++, min_char++)
572           {
573             void **val = table->contents.values + i;
574
575             if (val == default_value)
576               continue;
577             default_value = *val;
578             fprintf (mdebug__output, "\n%s  (U+%04X", prefix, min_char);
579             while (i + 1 < chartab_slots[depth]
580                    && val[1] == default_value)
581               i++, val++, min_char++;
582             fprintf (mdebug__output, "-U+%04X ", min_char);
583             if (key == Msymbol)
584               {
585                 if (default_value)
586                   fprintf (mdebug__output, "%s)",
587                            ((MSymbol) default_value)->name);
588                 else
589                   fprintf (mdebug__output, "nil)");
590               }
591             else
592               fprintf (mdebug__output, " #xx%X)", (unsigned) default_value);
593           }
594     }
595   fprintf (mdebug__output, ")");
596 }
597
598 \f
599 /* Internal API */
600
601 int
602 mchartable__init ()
603 {
604   M17N_OBJECT_ADD_ARRAY (chartable_table, "Chartable");
605   return 0;
606 }
607
608 void
609 mchartable__fini ()
610 {
611 }
612
613 void *
614 mchartable__lookup (MCharTable *table, int c, int *next_c, int default_p)
615 {
616   return lookup_chartable (&table->subtable, c, next_c, default_p);
617 }
618
619 /*** @} */
620 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
621
622 \f
623 /* External API */
624
625 /*** @addtogroup m17nChartable */
626 /*** @{ */
627 /*=*/
628
629 /***en
630     @brief Symbol whose name is "char-table".
631
632     The symbol @c Mchar_table has the name <tt>"char-table"</tt>.  */
633
634 /***ja
635     @brief "char-table" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
636
637     ¥·¥ó¥Ü¥ë @c Mchar_table ¤Ï̾Á° <tt>"char-table"</tt> ¤ò»ý¤Ä¡£
638     */
639
640 MSymbol Mchar_table;
641
642 /*=*/
643
644 /***en
645     @brief Create a new chartable.
646
647     The mchartable () function creates a new chartable object with
648     symbol $KEY and the default value $DEFAULT_VALUE.  If $KEY is a
649     managing key, the elements of the table (including the default
650     value) are managed objects or NULL.
651
652     @return
653     If the operation was successful, mchartable () returns a pointer
654     to the created chartable.  Otherwise it returns @c NULL and
655     assigns an error code to the external variable #merror_code.  */
656
657 /***ja
658     @brief ¿·¤·¤¤Ê¸»ú¥Æ¡¼¥Ö¥ë¤òºî¤ë.
659
660     ´Ø¿ô mchartable () ¤Ï¥­¡¼¤¬ $KEY ¤ÇÍ×ÁǤΥǥե©¥ë¥ÈÃͤ¬ 
661     $DEFAULT_VALUE ¤Ç¤¢¤ë¿·¤·¤¤Ê¸»ú¥Æ¡¼¥Ö¥ë¤òºî¤ë¡£¤â¤· $KEY 
662     ¤¬´ÉÍý¥­¡¼¤Ç¤¢¤ì¤Ð¡¢¤³¤Î¥Æ¡¼¥Ö¥ë¤ÎÍ×ÁǤϡʥǥե©¥ë¥ÈÃͤò´Þ¤á¤Æ¡Ë´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤« 
663     NULL ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
664
665     @return
666     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mchartable () ¤ÏºîÀ®¤µ¤ì¤¿Ê¸»ú¥Æ¡¼¥Ö¥ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
667     ¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
668
669 MCharTable *
670 mchartable (MSymbol key, void *default_value)
671 {
672   MCharTable *table;
673
674   M17N_OBJECT (table, free_chartable, MERROR_CHARTABLE);
675   M17N_OBJECT_REGISTER (chartable_table, table);
676   table->key = key;
677   table->min_char = -1;
678   table->max_char = -1;
679   SET_DEPTH_MIN_CHAR (&table->subtable, 0, 0);
680   table->subtable.default_value = default_value;
681   if (key != Mnil && key->managing_key && default_value)
682     M17N_OBJECT_REF (default_value);
683   table->subtable.contents.tables = NULL;
684   return table;
685 }
686
687 /*=*/
688
689 /***en
690     @brief Return the minimum character whose value is set in a chartabe.
691
692     The mchartable_min_char () function return the minimum character
693     whose value is set in chartable $TABLE.  No character is set its
694     value, the function returns -1.
695  */
696
697 int
698 mchartable_min_char (MCharTable *table)
699 {
700   return table->min_char;
701 }
702
703 /*=*/
704
705 /***en
706     @brief Return the maximum character whose value is set in a chartabe.
707
708     The mchartable_max_char () function return the maximum character
709     whose value is set in chartable $TABLE.  No character is set its
710     value, the function returns -1.
711  */
712
713 int
714 mchartable_max_char (MCharTable *table)
715 {
716   return table->max_char;
717 }
718
719 /*=*/
720
721 /***en
722     @brief Return the assigned value of a character in a chartable.
723
724     The mchartable_lookup () function returns the value assigned to
725     character $C in chartable $TABLE.  If no value has been set for $C
726     explicitly, the default value of $TABLE is returned.  If $C is not
727     a valid character, mchartable_lookup () returns @c NULL and
728     assigns an error code to the external variable #merror_code.  */
729
730 /***ja
731     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Çʸ»ú¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹.
732
733     ´Ø¿ô mchartable_lookup () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Çʸ»ú $C 
734     ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹¡£$C ¤ËÂФ¹¤ëÌÀ¼¨Åª¤ÊÃͤ¬¤Ê¤±¤ì¤Ð¡¢$TABLE 
735     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤòÊÖ¤¹¡£$C ¤¬ÂÅÅö¤Êʸ»ú¤Ç¤Ê¤±¤ì¤Ð¡¢mchartable_lookup () ¤Ï 
736     @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
737
738 /***
739     @errors
740     @c MERROR_CHAR
741
742     @seealso
743     mchartable_set ()  */
744
745 void *
746 mchartable_lookup (MCharTable *table, int c)
747 {
748   M_CHECK_CHAR (c, NULL);
749
750   if (c < table->min_char || c > table->max_char)
751     return table->subtable.default_value;
752   return lookup_chartable (&table->subtable, c, NULL, 0);
753 }
754
755 /*=*/
756
757 /***en
758     @brief Assign a value to a character in a chartable.
759
760     The mchartable_set () function sets the value of character $C in
761     chartable $TABLE to $VAL.
762
763     @return
764     If the operation was successful, mchartable_set () returns 0.
765     Otherwise it returns -1 and assigns an error code to the external
766     variable #merror_code.  */
767
768 /***ja
769     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Ç¤Îʸ»ú¤ÎÃͤòÀßÄꤹ¤ë.
770
771     ´Ø¿ô mchartable_set () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú $C 
772     ¤ËÃÍ $VAL ¤ò³ä¤êÅö¤Æ¤ë¡£
773
774     @return
775     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchartable_set () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
776     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
777
778 /***
779     @errors
780     @c MERROR_CHAR
781
782     @seealso
783     mchartable_lookup (), mchartable_set_range ()  */
784
785
786 int
787 mchartable_set (MCharTable *table, int c, void *val)
788 {
789   int managedp = table->key != Mnil && table->key->managing_key;
790   MSubCharTable *sub = &table->subtable;
791   int i;
792
793   M_CHECK_CHAR (c, -1);
794
795   if (table->max_char < 0)
796     table->min_char = table->max_char = c;
797   else
798     {
799       if (c < table->min_char)
800         table->min_char = c;
801       else if (c > table->max_char)
802         table->max_char = c;
803     }
804
805   for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++)
806     {
807       if (! sub->contents.tables)
808         {
809           if (sub->default_value == val)
810             return 0;
811           make_sub_tables (sub, managedp);
812         }
813       sub = sub->contents.tables + SUB_IDX (i, c);
814     }
815   if (! sub->contents.values)
816     {
817       if (sub->default_value == val)
818         return 0;
819       make_sub_values (sub, managedp);
820     }
821   sub->contents.values[SUB_IDX (3, c)] = val;
822   if (managedp && val)
823     M17N_OBJECT_REF (val);
824   return 0;
825 }
826
827 /*=*/
828
829 /***en
830     @brief Assign a value to the characters in the specified range.
831
832     The mchartable_set_range () function assigns value $VAL to the
833     characters from $FROM to $TO (both inclusive) in chartable $TABLE.
834
835     @return
836     If the operation was successful, mchartable_set_range () returns
837     0.  Otherwise it returns -1 and assigns an error code to the
838     external variable #merror_code.  If $FROM is greater than $TO,
839     mchartable_set_range () returns immediately without an error.  */
840
841 /***ja
842     @brief »ØÄêÈϰϤÎʸ»ú¤ËÃͤòÀßÄꤹ¤ë.
843
844     ´Ø¿ô mchartable_set_range () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Î $FROM 
845     ¤«¤é $TO ¤Þ¤Ç¡Êξü¤ò´Þ¤à¡Ë¤Îʸ»ú¤Ë¡¢ÃͤȤ·¤Æ $VAL ¤òÀßÄꤹ¤ë¡£
846
847     @return
848     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mchartable_set_range () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 
849     -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£$FROM ¤¬ 
850     $TO ¤è¤êÂ礭¤¤¤È¤­¤Ë¤Ï¡¢ mchartable_set_range () 
851     ¤Ï²¿¤â¤»¤º¡¢¥¨¥é¡¼¤âµ¯¤³¤µ¤Ê¤¤¡£  */
852
853 /***
854     @errors
855     @c MERROR_CHAR
856
857     @seealso
858     mchartable_set ()  */
859
860 int
861 mchartable_set_range (MCharTable *table, int from, int to, void *val)
862 {
863   int managedp = table->key != Mnil && table->key->managing_key;
864
865   M_CHECK_CHAR (from, -1);
866   M_CHECK_CHAR (to, -1);
867
868   if (from > to)
869     return 0;
870
871   if (table->max_char < 0)
872     table->min_char = from, table->max_char = to;
873   else{
874     if (from < table->min_char)
875       table->min_char = from;
876     if (to > table->max_char)
877       table->max_char = to;
878   }
879   set_chartable_range (&table->subtable, from, to, val, managedp);
880   return 0;
881 }
882
883 /*=*/
884
885 /***en
886     @brief Search for characters that have non-default value.
887
888     The mchartable_range () function searches chartable $TABLE for the
889     first and the last character codes that do not have the default
890     value of $TABLE, and set $FROM and $TO to them, respectively.  If
891     all characters have the default value, both $FROM and $TO are set
892     to -1.  */
893
894 /***ja
895     @brief Ãͤ¬¥Ç¥Õ¥©¥ë¥È¤È°Û¤Ê¤ëʸ»ú¤òõ¤¹.
896
897     ´Ø¿ô mchartable_range () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Ç¡¢$TABLE 
898     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͰʳ°¤ÎÃͤò»ý¤ÄºÇ½é¤ÈºÇ¸å¤Îʸ»ú¤òõ¤·¡¢¤½¤ì¤¾¤ì¤ò $FROM 
899     ¤È $TO ¤ËÀßÄꤹ¤ë¡£¤¹¤Ù¤Æ¤Îʸ»ú¤¬ÃͤȤ·¤Æ¥Ç¥Õ¥©¥ë¥ÈÃͤò¤È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï
900     $FROM ¤È $TO ¤ò -1¤ËÀßÄꤹ¤ë¡£  */
901
902 void
903 mchartable_range (MCharTable *table, int *from, int *to)
904 {
905   *from = chartab_min_non_default_char (&table->subtable,
906                                         table->subtable.default_value);
907   if (*from == -1)
908     *to = -1;
909   else
910     *to = chartab_max_non_default_char (&table->subtable,
911                                         table->subtable.default_value);
912 }
913
914 /*=*/
915
916 /***en
917     @brief Call a function for characters in a chartable.
918
919     The mchartable_map () function calls function $FUNC for characters
920     in chartable $TABLE.  No function call occurs for characters that
921     have value $IGNORE in $TABLE.  Comparison of $IGNORE and character
922     value is done with the operator @c ==.  Be careful when you use
923     string literals or pointers.
924
925     Instead of calling $FUNC for each character, mchartable_map ()
926     tries to optimize the number of function calls, i.e. it makes a
927     single function call for a chunk of characters when those
928     consecutive characters have the same value.
929
930     No matter how long the character chunk is, $FUNC is called with
931     four arguments; $FROM, $TO, $VAL, and $ARG.  $FROM and $TO (both
932     inclusive) defines the range of characters that have value $VAL.
933     $ARG is the same as $FUNC_ARG.
934
935     @return
936     This function always returns 0.  */
937
938 /***ja
939     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Îʸ»ú¤ËÂФ·¤Æ»ØÄê¤Î´Ø¿ô¤ò¸Æ¤Ö.
940
941     ´Ø¿ô mchartable_map () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú¤ËÂФ·¤Æ´Ø¿ô
942     $FUNC ¤ò¸Æ¤Ö¡£¤¿¤À¤·$TABLE Ãæ¤Ç¤âÃͤ¬ $IGNORE 
943     ¤Ç¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ê¤ï¤Ê¤¤¡£$IGNORE ¤Èʸ»ú¤ÎÃͤÎÈæ³Ó¤Ï 
944     @c == ¤Ç¹Ô¤Ê¤¦¤Î¤Ç¡¢Ê¸»úÎó¥ê¥Æ¥é¥ë¤ä¥Ý¥¤¥ó¥¿¤ò»È¤¦ºÝ¤Ë¤ÏÃí°Õ¤òÍפ¹¤ë¡£
945
946     mchartable_map () ¤Ï¡¢°ìʸ»ú¤´¤È¤Ë $FUNC 
947     ¤ò¸Æ¤Ö¤Î¤Ç¤Ï¤Ê¤¯¡¢´Ø¿ô¸Æ¤Ó½Ð¤·¤Î²ó¿ô¤òºÇŬ²½¤·¤è¤¦¤È¤¹¤ë¡£
948     ¤¹¤Ê¤ï¤Á¡¢Ï¢Â³¤·¤¿Ê¸»ú¤¬Æ±¤¸Ãͤò»ý¤Ã¤Æ¤¤¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤Îʸ»ú¤Î¤Þ¤È¤Þ¤êÁ´ÂΤˤĤ¤¤Æ°ìÅ٤δؿô¸Æ¤Ó½Ð
949     ¤·¤·¤«¹Ô¤Ê¤ï¤Ê¤¤¡£
950
951     Ê¸»ú¤Î¤Þ¤È¤Þ¤ê¤ÎÂ礭¤µ¤Ë¤«¤«¤ï¤é¤º¡¢$FUNC ¤Ï $FROM, $TO, $VAL, $ARG 
952     ¤Î£´°ú¿ô¤Ç¸Æ¤Ð¤ì¤ë¡£$FROM ¤È $TO ¡Êξü¤ò´Þ¤à¡Ë¤Ï $VAL 
953     ¤òÃͤȤ·¤Æ»ý¤Äʸ»ú¤ÎÈϰϤò¼¨¤·¡¢$ARG ¤Ï $FUNC_ARG ¤½¤Î¤â¤Î¤Ç¤¢¤ë¡£
954
955     @return
956     ¤³¤Î´Ø¿ô¤Ï¾ï¤Ë0¤òÊÖ¤¹¡£  */
957
958 int
959 mchartable_map (MCharTable *table, void *ignore,
960                 void (*func) (int, int, void *, void *),
961                 void *func_arg)
962 {
963   map_chartable (&table->subtable, ignore, 0, func, func_arg);
964   return 0;
965 }
966
967 /*=*/
968
969 /*** @} */
970
971 /*** @addtogroup m17nDebug */
972 /*=*/
973 /*** @{  */
974
975 /***en
976     @brief Dump a chartable.
977
978     The mdebug_dump_chartab () function prints a chartable $TABLE in a
979     human readable way to the stderr or to what specified by the
980     environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
981     many columns to indent the lines but the first one.
982
983     @return
984     This function returns $TABLE.  */
985
986 /***ja
987     @brief Ê¸»ú¥Æ¡¼¥Ö¥ë¤ò¥À¥ó¥×¤¹¤ë.
988
989     ´Ø¿ô mdebug_dump_chartab () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE ¤òɸ½à¥¨¥é¡¼½ÐÎÏ
990     ¤â¤·¤¯¤Ï´Ä¶­ÊÑ¿ô MDEBUG_DUMP_FONT ¤Ç»ØÄꤵ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë¿Í´Ö¤Ë²ÄÆÉ
991     ¤Ê·Á¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
992
993     @return
994     ¤³¤Î´Ø¿ô¤Ï $TABLE ¤òÊÖ¤¹¡£  */
995
996 MCharTable *
997 mdebug_dump_chartab (MCharTable *table, int indent)
998 {
999   fprintf (mdebug__output, "(chartab (U+%04X U+%04X)",
1000            table->min_char, table->max_char);
1001   dump_sub_chartab (&table->subtable, table->subtable.default_value,
1002                     table->key, indent + 2);
1003   fprintf (mdebug__output, ")");
1004   return table;
1005 }
1006
1007 /*** @} */
1008
1009 /*
1010   Local Variables:
1011   coding: euc-japan
1012   End:
1013 */