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