(mchartable__init): Initalize chartable_table.count.
[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., 59 Temple Place, Suite 330, Boston, MA
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 = 0;
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 assigned value of a character in a chartable.
690
691     The mchartable_lookup () function returns the value assigned to
692     character $C in chartable $TABLE.  If no value has been set for $C
693     explicitly, the default value of $TABLE is returned.  If $C is not
694     a valid character, mchartable_lookup () returns @c NULL and
695     assigns an error code to the external variable #merror_code.  */
696
697 /***ja
698     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Çʸ»ú¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹.
699
700     ´Ø¿ô mchartable_lookup () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Çʸ»ú $C 
701     ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹¡£$C ¤ËÂФ¹¤ëÌÀ¼¨Åª¤ÊÃͤ¬¤Ê¤±¤ì¤Ð¡¢$TABLE 
702     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤòÊÖ¤¹¡£$C ¤¬ÂÅÅö¤Êʸ»ú¤Ç¤Ê¤±¤ì¤Ð¡¢mchartable_lookup () ¤Ï 
703     @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
704
705 /***
706     @errors
707     @c MERROR_CHAR
708
709     @seealso
710     mchartable_set ()  */
711
712 void *
713 mchartable_lookup (MCharTable *table, int c)
714 {
715   M_CHECK_CHAR (c, NULL);
716
717   if (c < table->min_char || c > table->max_char)
718     return table->subtable.default_value;
719   return lookup_chartable (&table->subtable, c, NULL, 0);
720 }
721
722 /*=*/
723
724 /***en
725     @brief Assign a value to a character in a chartable.
726
727     The mchartable_set () function sets the value of character $C in
728     chartable $TABLE to $VAL.
729
730     @return
731     If the operation was successful, mchartable_set () returns 0.
732     Otherwise it returns -1 and assigns an error code to the external
733     variable #merror_code.  */
734
735 /***ja
736     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Ç¤Îʸ»ú¤ÎÃͤòÀßÄꤹ¤ë.
737
738     ´Ø¿ô mchartable_set () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú $C 
739     ¤ËÃÍ $VAL ¤ò³ä¤êÅö¤Æ¤ë¡£
740
741     @return
742     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchartable_set () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
743     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
744
745 /***
746     @errors
747     @c MERROR_CHAR
748
749     @seealso
750     mchartable_lookup (), mchartable_set_range ()  */
751
752
753 int
754 mchartable_set (MCharTable *table, int c, void *val)
755 {
756   int managedp = table->key != Mnil && table->key->managing_key;
757   MSubCharTable *sub = &table->subtable;
758   int i;
759
760   M_CHECK_CHAR (c, -1);
761
762   if (table->max_char < 0)
763     table->min_char = table->max_char = c;
764   else
765     {
766       if (c < table->min_char)
767         table->min_char = c;
768       else if (c > table->max_char)
769         table->max_char = c;
770     }
771
772   for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++)
773     {
774       if (! sub->contents.tables)
775         {
776           if (sub->default_value == val)
777             return 0;
778           make_sub_tables (sub, managedp);
779         }
780       sub = sub->contents.tables + SUB_IDX (i, c);
781     }
782   if (! sub->contents.values)
783     {
784       if (sub->default_value == val)
785         return 0;
786       make_sub_values (sub, managedp);
787     }
788   sub->contents.values[SUB_IDX (3, c)] = val;
789   if (managedp && val)
790     M17N_OBJECT_REF (val);
791   return 0;
792 }
793
794 /*=*/
795
796 /***en
797     @brief Assign a value to the characters in the specified range.
798
799     The mchartable_set_range () function assigns value $VAL to the
800     characters from $FROM to $TO (both inclusive) in chartable $TABLE.
801
802     @return
803     If the operation was successful, mchartable_set_range () returns
804     0.  Otherwise it returns -1 and assigns an error code to the
805     external variable #merror_code.  If $FROM is greater than $TO,
806     mchartable_set_range () returns immediately without an error.  */
807
808 /***ja
809     @brief »ØÄêÈϰϤÎʸ»ú¤ËÃͤòÀßÄꤹ¤ë.
810
811     ´Ø¿ô mchartable_set_range () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Î $FROM 
812     ¤«¤é $TO ¤Þ¤Ç¡Êξü¤ò´Þ¤à¡Ë¤Îʸ»ú¤Ë¡¢ÃͤȤ·¤Æ $VAL ¤òÀßÄꤹ¤ë¡£
813
814     @return
815     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mchartable_set_range () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 
816     -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£$FROM ¤¬ 
817     $TO ¤è¤êÂ礭¤¤¤È¤­¤Ë¤Ï¡¢ mchartable_set_range () 
818     ¤Ï²¿¤â¤»¤º¡¢¥¨¥é¡¼¤âµ¯¤³¤µ¤Ê¤¤¡£  */
819
820 /***
821     @errors
822     @c MERROR_CHAR
823
824     @seealso
825     mchartable_set ()  */
826
827 int
828 mchartable_set_range (MCharTable *table, int from, int to, void *val)
829 {
830   int managedp = table->key != Mnil && table->key->managing_key;
831
832   M_CHECK_CHAR (from, -1);
833   M_CHECK_CHAR (to, -1);
834
835   if (from > to)
836     return 0;
837
838   if (table->max_char < 0)
839     table->min_char = from, table->max_char = to;
840   else{
841     if (from < table->min_char)
842       table->min_char = from;
843     if (to > table->max_char)
844       table->max_char = to;
845   }
846   set_chartable_range (&table->subtable, from, to, val, managedp);
847   return 0;
848 }
849
850 /*=*/
851
852 /***en
853     @brief Search for characters that have non-default value.
854
855     The mchartable_range () function searches chartable $TABLE for the
856     first and the last character codes that do not have the default
857     value of $TABLE, and set $FROM and $TO to them, respectively.  If
858     all characters have the default value, both $FROM and $TO are set
859     to -1.  */
860
861 /***ja
862     @brief Ãͤ¬¥Ç¥Õ¥©¥ë¥È¤È°Û¤Ê¤ëʸ»ú¤òõ¤¹.
863
864     ´Ø¿ô mchartable_range () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Ç¡¢$TABLE 
865     ¤Î¥Ç¥Õ¥©¥ë¥ÈÃͰʳ°¤ÎÃͤò»ý¤ÄºÇ½é¤ÈºÇ¸å¤Îʸ»ú¤òõ¤·¡¢¤½¤ì¤¾¤ì¤ò $FROM 
866     ¤È $TO ¤ËÀßÄꤹ¤ë¡£¤¹¤Ù¤Æ¤Îʸ»ú¤¬ÃͤȤ·¤Æ¥Ç¥Õ¥©¥ë¥ÈÃͤò¤È¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï
867     $FROM ¤È $TO ¤ò -1¤ËÀßÄꤹ¤ë¡£  */
868
869 void
870 mchartable_range (MCharTable *table, int *from, int *to)
871 {
872   *from = chartab_min_non_default_char (&table->subtable,
873                                         table->subtable.default_value);
874   if (*from == -1)
875     *to = -1;
876   else
877     *to = chartab_max_non_default_char (&table->subtable,
878                                         table->subtable.default_value);
879 }
880
881 /*=*/
882
883 /***en
884     @brief Call a function for characters in a chartable.
885
886     The mchartable_map () function calls function $FUNC for characters
887     in chartable $TABLE.  No function call occurs for characters that
888     have value $IGNORE in $TABLE.  Comparison of $IGNORE and character
889     value is done with the operator @c ==.  Be careful when you use
890     string literals or pointers.
891
892     Instead of calling $FUNC for each character, mchartable_map ()
893     tries to optimize the number of function calls, i.e. it makes a
894     single function call for a chunk of characters when those
895     consecutive characters have the same value.
896
897     No matter how long the character chunk is, $FUNC is called with
898     four arguments; $FROM, $TO, $VAL, and $ARG.  $FROM and $TO (both
899     inclusive) defines the range of characters that have value $VAL.
900     $ARG is the same as $FUNC_ARG.
901
902     @return
903     This function always returns 0.  */
904
905 /***ja
906     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Îʸ»ú¤ËÂФ·¤Æ»ØÄê¤Î´Ø¿ô¤ò¸Æ¤Ö.
907
908     ´Ø¿ô mchartable_map () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú¤ËÂФ·¤Æ´Ø¿ô
909     $FUNC ¤ò¸Æ¤Ö¡£¤¿¤À¤·$TABLE Ãæ¤Ç¤âÃͤ¬ $IGNORE 
910     ¤Ç¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ê¤ï¤Ê¤¤¡£$IGNORE ¤Èʸ»ú¤ÎÃͤÎÈæ³Ó¤Ï 
911     @c == ¤Ç¹Ô¤Ê¤¦¤Î¤Ç¡¢Ê¸»úÎó¥ê¥Æ¥é¥ë¤ä¥Ý¥¤¥ó¥¿¤ò»È¤¦ºÝ¤Ë¤ÏÃí°Õ¤òÍפ¹¤ë¡£
912
913     mchartable_map () ¤Ï¡¢°ìʸ»ú¤´¤È¤Ë $FUNC 
914     ¤ò¸Æ¤Ö¤Î¤Ç¤Ï¤Ê¤¯¡¢´Ø¿ô¸Æ¤Ó½Ð¤·¤Î²ó¿ô¤òºÇŬ²½¤·¤è¤¦¤È¤¹¤ë¡£
915     ¤¹¤Ê¤ï¤Á¡¢Ï¢Â³¤·¤¿Ê¸»ú¤¬Æ±¤¸Ãͤò»ý¤Ã¤Æ¤¤¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤Îʸ»ú¤Î¤Þ¤È¤Þ¤êÁ´ÂΤˤĤ¤¤Æ°ìÅ٤δؿô¸Æ¤Ó½Ð
916     ¤·¤·¤«¹Ô¤Ê¤ï¤Ê¤¤¡£
917
918     Ê¸»ú¤Î¤Þ¤È¤Þ¤ê¤ÎÂ礭¤µ¤Ë¤«¤«¤ï¤é¤º¡¢$FUNC ¤Ï $FROM, $TO, $VAL, $ARG 
919     ¤Î£´°ú¿ô¤Ç¸Æ¤Ð¤ì¤ë¡£$FROM ¤È $TO ¡Êξü¤ò´Þ¤à¡Ë¤Ï $VAL 
920     ¤òÃͤȤ·¤Æ»ý¤Äʸ»ú¤ÎÈϰϤò¼¨¤·¡¢$ARG ¤Ï $FUNC_ARG ¤½¤Î¤â¤Î¤Ç¤¢¤ë¡£
921
922     @return
923     ¤³¤Î´Ø¿ô¤Ï¾ï¤Ë0¤òÊÖ¤¹¡£  */
924
925 int
926 mchartable_map (MCharTable *table, void *ignore,
927                 void (*func) (int, int, void *, void *),
928                 void *func_arg)
929 {
930   map_chartable (&table->subtable, ignore, 0, func, func_arg);
931   return 0;
932 }
933
934 /*=*/
935
936 /*** @} */
937
938 /*** @addtogroup m17nDebug */
939 /*=*/
940 /*** @{  */
941
942 /***en
943     @brief Dump a chartable.
944
945     The mdebug_dump_chartab () function prints a chartable $TABLE in a
946     human readable way to the stderr.  $INDENT specifies how many
947     columns to indent the lines but the first one.
948
949     @return
950     This function returns $TABLE.  */
951
952 /***ja
953     @brief Ê¸»ú¥Æ¡¼¥Ö¥ë¤ò¥À¥ó¥×¤¹¤ë.
954
955     ´Ø¿ô mdebug_dump_chartab () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE ¤ò stderr 
956     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£$INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
957
958     @return
959     ¤³¤Î´Ø¿ô¤Ï $TABLE ¤òÊÖ¤¹¡£  */
960
961 MCharTable *
962 mdebug_dump_chartab (MCharTable *table, int indent)
963 {
964   fprintf (stderr, "(chartab (U+%04X U+%04X)",
965            table->min_char, table->max_char);
966   dump_sub_chartab (&table->subtable, table->subtable.default_value,
967                     table->key, indent + 2);
968   fprintf (stderr, ")");
969   return table;
970 }
971
972 /*** @} */
973
974 /*
975   Local Variables:
976   coding: euc-japan
977   End:
978 */