merge FLT
[m17n/m17n-lib.git] / src / chartab.c
1 /* chartab.h -- character table module.
2    Copyright (C) 2003, 2004
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 (stderr, "\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 (stderr, "(default %s)",
556                  ((MSymbol) table->default_value)->name);
557       else
558         fprintf (stderr, "(default nil)");
559     }
560   else
561     fprintf (stderr, "(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 (stderr, "\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 (stderr, "-U+%04X ", min_char);
583             if (key == Msymbol)
584               {
585                 if (default_value)
586                   fprintf (stderr, "%s)", ((MSymbol) default_value)->name);
587                 else
588                   fprintf (stderr, "nil)");
589               }
590             else
591               fprintf (stderr, " #xx%X)", (unsigned) default_value);
592           }
593     }
594   fprintf (stderr, ")");
595 }
596
597 \f
598 /* Internal API */
599
600 int
601 mchartable__init ()
602 {
603   M17N_OBJECT_ADD_ARRAY (chartable_table, "Chartable");
604   return 0;
605 }
606
607 void
608 mchartable__fini ()
609 {
610 }
611
612 void *
613 mchartable__lookup (MCharTable *table, int c, int *next_c, int default_p)
614 {
615   return lookup_chartable (&table->subtable, c, next_c, default_p);
616 }
617
618 /*** @} */
619 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
620
621 \f
622 /* External API */
623
624 /*** @addtogroup m17nChartable */
625 /*** @{ */
626 /*=*/
627
628 /***en
629     @brief Symbol whose name is "char-table".
630
631     The symbol @c Mchar_table has the name <tt>"char-table"</tt>.  */
632
633 /***ja
634     @brief "char-table" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
635
636     ¥·¥ó¥Ü¥ë @c Mchar_table ¤Ï̾Á° <tt>"char-table"</tt> ¤ò»ý¤Ä¡£
637     */
638
639 MSymbol Mchar_table;
640
641 /*=*/
642
643 /***en
644     @brief Create a new chartable.
645
646     The mchartable () function creates a new chartable object with
647     symbol $KEY and the default value $DEFAULT_VALUE.  If $KEY is a
648     managing key, the elements of the table (including the default
649     value) are managed objects or NULL.
650
651     @return
652     If the operation was successful, mchartable () returns a pointer
653     to the created chartable.  Otherwise it returns @c NULL and
654     assigns an error code to the external variable #merror_code.  */
655
656 /***ja
657     @brief ¿·¤·¤¤Ê¸»ú¥Æ¡¼¥Ö¥ë¤òºî¤ë.
658
659     ´Ø¿ô mchartable () ¤Ï¥­¡¼¤¬ $KEY ¤ÇÍ×ÁǤΥǥե©¥ë¥ÈÃͤ¬ 
660     $DEFAULT_VALUE ¤Ç¤¢¤ë¿·¤·¤¤Ê¸»ú¥Æ¡¼¥Ö¥ë¤òºî¤ë¡£¤â¤· $KEY 
661     ¤¬´ÉÍý¥­¡¼¤Ç¤¢¤ì¤Ð¡¢¤³¤Î¥Æ¡¼¥Ö¥ë¤ÎÍ×ÁǤϡʥǥե©¥ë¥ÈÃͤò´Þ¤á¤Æ¡Ë´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤« 
662     NULL ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
663
664     @return
665     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mchartable () ¤ÏºîÀ®¤µ¤ì¤¿Ê¸»ú¥Æ¡¼¥Ö¥ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
666     ¼ºÇÔ¤·¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
667
668 MCharTable *
669 mchartable (MSymbol key, void *default_value)
670 {
671   MCharTable *table;
672
673   M17N_OBJECT (table, free_chartable, MERROR_CHARTABLE);
674   M17N_OBJECT_REGISTER (chartable_table, table);
675   table->key = key;
676   table->min_char = -1;
677   table->max_char = -1;
678   SET_DEPTH_MIN_CHAR (&table->subtable, 0, 0);
679   table->subtable.default_value = default_value;
680   if (key != Mnil && key->managing_key && default_value)
681     M17N_OBJECT_REF (default_value);
682   table->subtable.contents.tables = NULL;
683   return table;
684 }
685
686 /*=*/
687
688 /***en
689     @brief Return the minimum character whose value is set in a chartabe.
690
691     The mchartable_min_char () function return the minimum character
692     whose value is set in chartable $TABLE.  No character is set its
693     value, the function returns -1.
694  */
695
696 int
697 mchartable_min_char (MCharTable *table)
698 {
699   return table->min_char;
700 }
701
702 /*=*/
703
704 /***en
705     @brief Return the maximum character whose value is set in a chartabe.
706
707     The mchartable_max_char () function return the maximum character
708     whose value is set in chartable $TABLE.  No character is set its
709     value, the function returns -1.
710  */
711
712 int
713 mchartable_max_char (MCharTable *table)
714 {
715   return table->max_char;
716 }
717
718 /*=*/
719
720 /***en
721     @brief Return the assigned value of a character in a chartable.
722
723     The mchartable_lookup () function returns the value assigned to
724     character $C in chartable $TABLE.  If no value has been set for $C
725     explicitly, the default value of $TABLE is returned.  If $C is not
726     a valid character, mchartable_lookup () returns @c NULL and
727     assigns an error code to the external variable #merror_code.  */
728
729 /***ja
730     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Çʸ»ú¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹.
731
732     ´Ø¿ô mchartable_lookup () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Çʸ»ú $C 
733     ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹¡£$C ¤ËÂФ¹¤ëÌÀ¼¨Åª¤ÊÃͤ¬¤Ê¤±¤ì¤Ð¡¢$TABLE 
734     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤòÊÖ¤¹¡£$C ¤¬ÂÅÅö¤Êʸ»ú¤Ç¤Ê¤±¤ì¤Ð¡¢mchartable_lookup () ¤Ï 
735     @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
736
737 /***
738     @errors
739     @c MERROR_CHAR
740
741     @seealso
742     mchartable_set ()  */
743
744 void *
745 mchartable_lookup (MCharTable *table, int c)
746 {
747   M_CHECK_CHAR (c, NULL);
748
749   if (c < table->min_char || c > table->max_char)
750     return table->subtable.default_value;
751   return lookup_chartable (&table->subtable, c, NULL, 0);
752 }
753
754 /*=*/
755
756 /***en
757     @brief Assign a value to a character in a chartable.
758
759     The mchartable_set () function sets the value of character $C in
760     chartable $TABLE to $VAL.
761
762     @return
763     If the operation was successful, mchartable_set () returns 0.
764     Otherwise it returns -1 and assigns an error code to the external
765     variable #merror_code.  */
766
767 /***ja
768     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Ç¤Îʸ»ú¤ÎÃͤòÀßÄꤹ¤ë.
769
770     ´Ø¿ô mchartable_set () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú $C 
771     ¤ËÃÍ $VAL ¤ò³ä¤êÅö¤Æ¤ë¡£
772
773     @return
774     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchartable_set () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
775     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
776
777 /***
778     @errors
779     @c MERROR_CHAR
780
781     @seealso
782     mchartable_lookup (), mchartable_set_range ()  */
783
784
785 int
786 mchartable_set (MCharTable *table, int c, void *val)
787 {
788   int managedp = table->key != Mnil && table->key->managing_key;
789   MSubCharTable *sub = &table->subtable;
790   int i;
791
792   M_CHECK_CHAR (c, -1);
793
794   if (table->max_char < 0)
795     table->min_char = table->max_char = c;
796   else
797     {
798       if (c < table->min_char)
799         table->min_char = c;
800       else if (c > table->max_char)
801         table->max_char = c;
802     }
803
804   for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++)
805     {
806       if (! sub->contents.tables)
807         {
808           if (sub->default_value == val)
809             return 0;
810           make_sub_tables (sub, managedp);
811         }
812       sub = sub->contents.tables + SUB_IDX (i, c);
813     }
814   if (! sub->contents.values)
815     {
816       if (sub->default_value == val)
817         return 0;
818       make_sub_values (sub, managedp);
819     }
820   sub->contents.values[SUB_IDX (3, c)] = val;
821   if (managedp && val)
822     M17N_OBJECT_REF (val);
823   return 0;
824 }
825
826 /*=*/
827
828 /***en
829     @brief Assign a value to the characters in the specified range.
830
831     The mchartable_set_range () function assigns value $VAL to the
832     characters from $FROM to $TO (both inclusive) in chartable $TABLE.
833
834     @return
835     If the operation was successful, mchartable_set_range () returns
836     0.  Otherwise it returns -1 and assigns an error code to the
837     external variable #merror_code.  If $FROM is greater than $TO,
838     mchartable_set_range () returns immediately without an error.  */
839
840 /***ja
841     @brief »ØÄêÈϰϤÎʸ»ú¤ËÃͤòÀßÄꤹ¤ë.
842
843     ´Ø¿ô mchartable_set_range () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Î $FROM 
844     ¤«¤é $TO ¤Þ¤Ç¡Êξü¤ò´Þ¤à¡Ë¤Îʸ»ú¤Ë¡¢ÃͤȤ·¤Æ $VAL ¤òÀßÄꤹ¤ë¡£
845
846     @return
847     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mchartable_set_range () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 
848     -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£$FROM ¤¬ 
849     $TO ¤è¤êÂ礭¤¤¤È¤­¤Ë¤Ï¡¢ mchartable_set_range () 
850     ¤Ï²¿¤â¤»¤º¡¢¥¨¥é¡¼¤âµ¯¤³¤µ¤Ê¤¤¡£  */
851
852 /***
853     @errors
854     @c MERROR_CHAR
855
856     @seealso
857     mchartable_set ()  */
858
859 int
860 mchartable_set_range (MCharTable *table, int from, int to, void *val)
861 {
862   int managedp = table->key != Mnil && table->key->managing_key;
863
864   M_CHECK_CHAR (from, -1);
865   M_CHECK_CHAR (to, -1);
866
867   if (from > to)
868     return 0;
869
870   if (table->max_char < 0)
871     table->min_char = from, table->max_char = to;
872   else{
873     if (from < table->min_char)
874       table->min_char = from;
875     if (to > table->max_char)
876       table->max_char = to;
877   }
878   set_chartable_range (&table->subtable, from, to, val, managedp);
879   return 0;
880 }
881
882 /*=*/
883
884 /***en
885     @brief Search for characters that have non-default value.
886
887     The mchartable_range () function searches chartable $TABLE for the
888     first and the last character codes that do not have the default
889     value of $TABLE, and set $FROM and $TO to them, respectively.  If
890     all characters have the default value, both $FROM and $TO are set
891     to -1.  */
892
893 /***ja
894     @brief Ãͤ¬¥Ç¥Õ¥©¥ë¥È¤È°Û¤Ê¤ëʸ»ú¤òõ¤¹.
895
896     ´Ø¿ô mchartable_range () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Ç¡¢$TABLE 
897     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͰʳ°¤ÎÃͤò»ý¤ÄºÇ½é¤ÈºÇ¸å¤Îʸ»ú¤òõ¤·¡¢¤½¤ì¤¾¤ì¤ò $FROM 
898     ¤È $TO ¤ËÀßÄꤹ¤ë¡£¤¹¤Ù¤Æ¤Îʸ»ú¤¬ÃͤȤ·¤Æ¥Ç¥Õ¥©¥ë¥ÈÃͤò¤È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï
899     $FROM ¤È $TO ¤ò -1¤ËÀßÄꤹ¤ë¡£  */
900
901 void
902 mchartable_range (MCharTable *table, int *from, int *to)
903 {
904   *from = chartab_min_non_default_char (&table->subtable,
905                                         table->subtable.default_value);
906   if (*from == -1)
907     *to = -1;
908   else
909     *to = chartab_max_non_default_char (&table->subtable,
910                                         table->subtable.default_value);
911 }
912
913 /*=*/
914
915 /***en
916     @brief Call a function for characters in a chartable.
917
918     The mchartable_map () function calls function $FUNC for characters
919     in chartable $TABLE.  No function call occurs for characters that
920     have value $IGNORE in $TABLE.  Comparison of $IGNORE and character
921     value is done with the operator @c ==.  Be careful when you use
922     string literals or pointers.
923
924     Instead of calling $FUNC for each character, mchartable_map ()
925     tries to optimize the number of function calls, i.e. it makes a
926     single function call for a chunk of characters when those
927     consecutive characters have the same value.
928
929     No matter how long the character chunk is, $FUNC is called with
930     four arguments; $FROM, $TO, $VAL, and $ARG.  $FROM and $TO (both
931     inclusive) defines the range of characters that have value $VAL.
932     $ARG is the same as $FUNC_ARG.
933
934     @return
935     This function always returns 0.  */
936
937 /***ja
938     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Îʸ»ú¤ËÂФ·¤Æ»ØÄê¤Î´Ø¿ô¤ò¸Æ¤Ö.
939
940     ´Ø¿ô mchartable_map () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú¤ËÂФ·¤Æ´Ø¿ô
941     $FUNC ¤ò¸Æ¤Ö¡£¤¿¤À¤·$TABLE Ãæ¤Ç¤âÃͤ¬ $IGNORE 
942     ¤Ç¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ê¤ï¤Ê¤¤¡£$IGNORE ¤Èʸ»ú¤ÎÃͤÎÈæ³Ó¤Ï 
943     @c == ¤Ç¹Ô¤Ê¤¦¤Î¤Ç¡¢Ê¸»úÎó¥ê¥Æ¥é¥ë¤ä¥Ý¥¤¥ó¥¿¤ò»È¤¦ºÝ¤Ë¤ÏÃí°Õ¤òÍפ¹¤ë¡£
944
945     mchartable_map () ¤Ï¡¢°ìʸ»ú¤´¤È¤Ë $FUNC 
946     ¤ò¸Æ¤Ö¤Î¤Ç¤Ï¤Ê¤¯¡¢´Ø¿ô¸Æ¤Ó½Ð¤·¤Î²ó¿ô¤òºÇŬ²½¤·¤è¤¦¤È¤¹¤ë¡£
947     ¤¹¤Ê¤ï¤Á¡¢Ï¢Â³¤·¤¿Ê¸»ú¤¬Æ±¤¸Ãͤò»ý¤Ã¤Æ¤¤¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤Îʸ»ú¤Î¤Þ¤È¤Þ¤êÁ´ÂΤˤĤ¤¤Æ°ìÅ٤δؿô¸Æ¤Ó½Ð
948     ¤·¤·¤«¹Ô¤Ê¤ï¤Ê¤¤¡£
949
950     Ê¸»ú¤Î¤Þ¤È¤Þ¤ê¤ÎÂ礭¤µ¤Ë¤«¤«¤ï¤é¤º¡¢$FUNC ¤Ï $FROM, $TO, $VAL, $ARG 
951     ¤Î£´°ú¿ô¤Ç¸Æ¤Ð¤ì¤ë¡£$FROM ¤È $TO ¡Êξü¤ò´Þ¤à¡Ë¤Ï $VAL 
952     ¤òÃͤȤ·¤Æ»ý¤Äʸ»ú¤ÎÈϰϤò¼¨¤·¡¢$ARG ¤Ï $FUNC_ARG ¤½¤Î¤â¤Î¤Ç¤¢¤ë¡£
953
954     @return
955     ¤³¤Î´Ø¿ô¤Ï¾ï¤Ë0¤òÊÖ¤¹¡£  */
956
957 int
958 mchartable_map (MCharTable *table, void *ignore,
959                 void (*func) (int, int, void *, void *),
960                 void *func_arg)
961 {
962   map_chartable (&table->subtable, ignore, 0, func, func_arg);
963   return 0;
964 }
965
966 /*=*/
967
968 /*** @} */
969
970 /*** @addtogroup m17nDebug */
971 /*=*/
972 /*** @{  */
973
974 /***en
975     @brief Dump a chartable.
976
977     The mdebug_dump_chartab () function prints a chartable $TABLE in a
978     human readable way to the stderr.  $INDENT specifies how many
979     columns to indent the lines but the first one.
980
981     @return
982     This function returns $TABLE.  */
983
984 /***ja
985     @brief Ê¸»ú¥Æ¡¼¥Ö¥ë¤ò¥À¥ó¥×¤¹¤ë.
986
987     ´Ø¿ô mdebug_dump_chartab () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE ¤ò stderr 
988     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
989
990     @return
991     ¤³¤Î´Ø¿ô¤Ï $TABLE ¤òÊÖ¤¹¡£  */
992
993 MCharTable *
994 mdebug_dump_chartab (MCharTable *table, int indent)
995 {
996   fprintf (stderr, "(chartab (U+%04X U+%04X)",
997            table->min_char, table->max_char);
998   dump_sub_chartab (&table->subtable, table->subtable.default_value,
999                     table->key, indent + 2);
1000   fprintf (stderr, ")");
1001   return table;
1002 }
1003
1004 /*** @} */
1005
1006 /*
1007   Local Variables:
1008   coding: euc-japan
1009   End:
1010 */