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