*** 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     ¤è¤¦¤Ê¾õ¶·¤Ë¤ª¤¤¤Æ¸úΨŪ¤Ë¾ðÊó¤ò³ÊǼ¤Ç¤­¤ë¤â¤Î¤È¤·¤Æ¡¢m17n ¥é¥¤¥Ö
55     ¥é¥ê¤Ï @e Ê¸»ú¥Æ¡¼¥Ö¥ë (chartable) ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤òÍѤ¤¤ë¡£¥¢
56     ¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë¤òÇÛÎó¤Î°ì¼ï¤È¸«¤Ê¤¹¤³¤È¤¬
57     ¤Ç¤­¤ë¡£¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤ÎÆÃÄê¤Î¾ðÊó¤Ï¡¢¤½¤Î¾ðÊó¤ò»ý¤Äʸ»ú¥Æ¡¼¥Ö¥ë
58     ¤ò¤½¤Îʸ»ú¤Î¥³¡¼¥É¤Ç°ú¤¯¤³¤È¤ÇÆÀ¤é¤ì¤ë¡£  */
59
60 /*=*/
61 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
62 /*** @addtogroup m17nInternal
63      @{ */
64
65 #include <config.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <limits.h>
69 #include <ctype.h>
70 #include <stdio.h>
71
72 #include "m17n.h"
73 #include "m17n-misc.h"
74 #include "internal.h"
75 #include "symbol.h"
76
77 static M17NObjectArray chartable_table;
78
79 /*** Maximum depth of char-table.  */
80 #define CHAR_TAB_MAX_DEPTH 3
81
82 /** @name Define: Number of characters covered by char-table of each level.
83     @{ */
84
85 /** BITs for number of characters covered by char-table of each
86     level.  */
87 #if MCHAR_MAX < 0x400000
88
89 #define SUB_BITS_0      22      /* i.e. 0x400000 chars */
90 #define SUB_BITS_1      16      /* i.e. 0x10000 chars */
91 #define SUB_BITS_2      12      /* i.e. 0x1000 chars */
92 #define SUB_BITS_3      7       /* i.e. 0x80 chars */
93
94 #else  /* MCHAR_MAX >= 0x400000 */
95
96 #define SUB_BITS_0      31
97 #define SUB_BITS_1      24
98 #define SUB_BITS_2      16
99 #define SUB_BITS_3      8
100 #endif
101
102 /** @} */
103
104 /** How many characters a char-table covers at each level.  */
105 static const int chartab_chars[] =
106   { (1 << SUB_BITS_0),
107     (1 << SUB_BITS_1),
108     (1 << SUB_BITS_2),
109     (1 << SUB_BITS_3) };
110
111 /** How many slots a char-table has at each level.  */
112 static const int chartab_slots[] =
113   { (1 << (SUB_BITS_0 - SUB_BITS_1)),
114     (1 << (SUB_BITS_1 - SUB_BITS_2)),
115     (1 << (SUB_BITS_2 - SUB_BITS_3)),
116     (1 << SUB_BITS_3) };
117
118 /** Mask bits to obtain the valid bits from a character code for looking
119     up a char-table of each level.  */
120 static const int chartab_mask[] =
121   { (int) ((((unsigned) 1) << SUB_BITS_0) - 1),
122     (1 << SUB_BITS_1) - 1,
123     (1 << SUB_BITS_2) - 1,
124     (1 << SUB_BITS_3) - 1 };
125
126 /** Bit-shifting counts to obtain a valid index from a character code
127     for looking up a char-table of each level.  */
128 static const int chartab_shift[] =
129   { SUB_BITS_1, SUB_BITS_2, SUB_BITS_3, 0 };
130
131
132 /** Index for looking up character C in a char-table at DEPTH.  */
133 #define SUB_IDX(depth, c)       \
134   (((c) & chartab_mask[depth]) >> chartab_shift[depth])
135
136
137 /** Structure of sub char-table.  */
138 typedef struct MSubCharTable MSubCharTable;
139
140 struct MSubCharTable
141 {
142 #if SUB_BITS_0 > 24
143
144   /* The depth of the table; 0, 1, 2, or 3. */
145   int depth;
146
147   /* The minimum character covered by the table.  */
148   int min_char;
149
150 #else  /* SUB_BITS_0 <= 24 */
151
152   /* The value is ((<depth> << 24) | <min_char>).  */
153   int depth_min_char;
154
155 #endif  /* SUB_BITS_0 <= 24 */
156
157   /** The default value of characters covered by the table.  */
158   void *default_value;
159
160   /** For a table of bottom level, array of values.  For a non-bottom
161      table, array of sub char-tables.  It may be NULL if all
162      characters covered by the table has <default_value>.  */
163   union {
164     void **values;
165     MSubCharTable *tables;
166   } contents;
167 };
168
169 #if SUB_BITS_0 > 24
170 #define TABLE_DEPTH(table) ((table)->depth)
171 #define TABLE_MIN_CHAR(table) ((table)->min_char)
172 #define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
173   ((table)->depth = (DEPTH), (table)->min_char = (MIN_CHAR))
174 #else  /* SUB_BITS_0 <= 24 */
175 #define TABLE_DEPTH(table) ((table)->depth_min_char >> 24)
176 #define TABLE_MIN_CHAR(table) ((table)->depth_min_char & 0xFFFFFF)
177 #define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \
178   ((table)->depth_min_char = ((DEPTH) << 24) | (MIN_CHAR))
179 #endif  /* SUB_BITS_0 <= 24 */
180
181 /** Structure of char-table.  */
182
183 struct MCharTable
184 {
185   /** Common header for a managed object.  */
186   M17NObject control;
187
188   /** Key of the table.  */
189   MSymbol key;
190
191   /** The minimum and maximum characters covered by the table.  */
192   int min_char, max_char;
193
194   MSubCharTable subtable;
195 };
196
197
198 \f
199
200 /* Local functions.  */
201
202 /** Allocate and initialize an array of sub-tables for sub char-table
203     TABLE.  It is assumed that TABLE_DEPTH (TABLE) <
204     CHAR_TAB_MAX_DEPTH.*/
205
206 static void
207 make_sub_tables (MSubCharTable *table, int managedp)
208 {
209   int depth = TABLE_DEPTH (table);
210   int min_char = TABLE_MIN_CHAR (table);
211   int slots = chartab_slots[depth];
212   int chars = chartab_chars[depth + 1];
213   MSubCharTable *tables;
214   int i;
215
216   MTABLE_MALLOC (tables, slots, MERROR_CHARTABLE);
217
218   for (i = 0; i < slots; i++, min_char += chars)
219     {
220       SET_DEPTH_MIN_CHAR (tables + i, depth + 1, min_char);
221       tables[i].default_value = table->default_value;
222       tables[i].contents.tables = NULL;
223     }
224   if (managedp && table->default_value)
225     M17N_OBJECT_REF_NTIMES (tables->default_value, slots);
226   table->contents.tables = tables;
227 }
228
229
230 /** Allocate and initialize an array of values for sub char-table
231     TABLE.  It is assumed that TABLE_DEPTH (TABLE) ==
232     CHAR_TAB_MAX_DEPTH.  */
233
234 static void
235 make_sub_values (MSubCharTable *table, int managedp)
236 {
237   int slots = chartab_slots[CHAR_TAB_MAX_DEPTH];
238   void **values;
239   int i;
240
241   MTABLE_MALLOC (values, slots, MERROR_CHARTABLE);
242
243   for (i = 0; i < slots; i++)
244     values[i] = table->default_value;
245   if (managedp && table->default_value)
246     M17N_OBJECT_REF_NTIMES (table->default_value, slots);
247   table->contents.values = values;
248 }
249
250
251 /** Free contents of sub char-table TABLE and the default value of
252     TABLE.  Free also the sub-tables recursively.  */
253
254 static void
255 free_sub_tables (MSubCharTable *table, int managedp)
256 {
257   int depth = TABLE_DEPTH (table);
258   int slots = chartab_slots[depth];
259
260   if (table->contents.tables)
261     {
262       if (depth < CHAR_TAB_MAX_DEPTH)
263         {
264           while (slots--)
265             free_sub_tables (table->contents.tables + slots, managedp);
266           free (table->contents.tables);
267         }
268       else
269         {
270           if (managedp)
271             while (slots--)
272               {
273                 if (table->contents.values[slots])
274                   M17N_OBJECT_UNREF (table->contents.values[slots]);
275               }
276           free (table->contents.values);
277         }
278       table->contents.tables = NULL;
279     }
280   if (managedp && table->default_value)
281     M17N_OBJECT_UNREF (table->default_value);
282 }
283
284
285 /** In sub char-table TABLE, set value VAL for characters of the range
286     FROM and TO. */
287
288 static void
289 set_chartable_range (MSubCharTable *table, int from, int to, void *val,
290                      int managedp)
291 {
292   int depth = TABLE_DEPTH (table);
293   int min_char = TABLE_MIN_CHAR (table);
294   int max_char = min_char + (chartab_chars[depth] - 1);
295   int i;
296
297   if (max_char < 0 || max_char > MCHAR_MAX)
298     max_char = MCHAR_MAX;
299
300   if (from < min_char)
301     from = min_char;
302   if (to > max_char)
303     to = max_char;
304
305   if (from == min_char && to == max_char)
306     {
307       free_sub_tables (table, managedp);
308       if (managedp && val)
309         M17N_OBJECT_REF (val);
310       table->default_value = val;
311       return;
312     }
313
314   if (depth < CHAR_TAB_MAX_DEPTH)
315     {
316       if (! table->contents.tables)
317         make_sub_tables (table, managedp);
318       i = SUB_IDX (depth, from);
319       table = table->contents.tables + i;
320       while (i < chartab_slots[depth] && TABLE_MIN_CHAR (table) <= to)
321         {
322           set_chartable_range (table, from, to, val, managedp);
323           table++, i++;
324         }
325     }
326   else
327     {
328       int idx_from = SUB_IDX (depth, from);
329       int idx_to = SUB_IDX (depth, to);
330
331       if (! table->contents.values)
332         make_sub_values (table, managedp);
333       for (i = idx_from; i <= idx_to; i++)
334         {
335           if (managedp && table->contents.values[i])
336             M17N_OBJECT_UNREF (table->contents.values[i]);
337           table->contents.values[i] = val;
338         }
339       if (managedp && val)
340         M17N_OBJECT_REF_NTIMES (val, (idx_to - idx_from + 1));
341     }
342 }
343
344
345 /** Lookup the sub char-table TABLE for the character C.  If NEXT_C is
346     not NULL, set *NEXT_C to the next interesting character to lookup
347     for.  If DEFAULT_P is zero, the next interesting character is what
348     possibly has the different value than C.  Otherwise, the next
349     interesting character is what possibly has the default value (if C
350     has a value deferent from the default value) or has a value
351     different from the default value (if C has the default value).  */
352
353 static void *
354 lookup_chartable (MSubCharTable *table, int c, int *next_c, int default_p)
355 {
356   int depth = TABLE_DEPTH (table);
357   void *val;
358   void *default_value = table->default_value;
359   int idx;
360
361   while (1)
362     {
363       if (! table->contents.tables)
364         {
365           if (next_c)
366             *next_c = TABLE_MIN_CHAR (table) + chartab_chars[depth];
367           return table->default_value;
368         }
369       if (depth == CHAR_TAB_MAX_DEPTH)
370         break;
371       table = table->contents.tables + SUB_IDX (depth, c);
372       depth++;
373     }
374
375   idx = SUB_IDX (depth, c);
376   val = table->contents.values[idx];
377
378   if (next_c)
379     {
380       int max_char = TABLE_MIN_CHAR (table) + (chartab_chars[depth] - 1);
381
382       if (max_char < 0 || max_char > MCHAR_MAX)
383         max_char = MCHAR_MAX;
384       if (default_p && val != default_value)
385         {
386           do { c++, idx++; }
387           while (c >= 0 && c <= max_char
388                  && table->contents.values[idx] != default_value);
389         }
390       else
391         {
392           do { c++, idx++; }
393           while (c >= 0 && c <= max_char
394                  && table->contents.values[idx] == val);
395         }
396       *next_c = c;
397     }
398   return val;
399 }
400
401 /** Call FUNC for characters in sub char-table TABLE.  Ignore such
402     characters that has a value IGNORE.  FUNC is called with four
403     arguments; FROM, TO, VAL, and ARG (same as FUNC_ARG).  If
404     DEFAULT_P is zero, FROM and TO are range of characters that has
405     the same value VAL.  Otherwise, FROM and TO are range of
406     characters that has the different value than the default value of
407     TABLE.  */
408
409 static void
410 map_chartable (MSubCharTable *table, void *ignore, int default_p,
411                 void (*func) (int, int, void *, void *),
412                 void *func_arg)
413 {
414   void *current;
415   int from = 0;
416   int c, next_c;
417
418   current = lookup_chartable (table, 0, &next_c, default_p);
419   c = next_c;
420   while (c >= 0 && c <= MCHAR_MAX)
421     {
422       void *next = lookup_chartable (table, c, &next_c, default_p);
423
424       if (current != next)
425         {
426           if (current != ignore)
427             (*func) (from, c - 1, current, func_arg);
428           current = next;
429           from = c;
430         }
431       c = next_c;
432     }
433   if (from <= MCHAR_MAX && current != ignore)
434     (*func) (from, MCHAR_MAX, current, func_arg);
435 }
436
437
438 /* Return the smallest character whose value is not DEFAULT_VALUE in
439    TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
440    -1.  */
441
442 static int
443 chartab_min_non_default_char (MSubCharTable *table, void *default_value)
444 {
445   int depth = TABLE_DEPTH (table);
446   int slots;
447   int i, c;
448
449   if (!table->contents.tables)
450     return (default_value == table->default_value
451             ? -1 : TABLE_MIN_CHAR (table));
452
453   slots = chartab_slots[depth];
454
455   if (depth == CHAR_TAB_MAX_DEPTH)
456     {
457       for (i = 0; i < slots; i++)
458         if (table->contents.values[i] != default_value)
459           return (TABLE_MIN_CHAR (table) + i);
460     }
461   else
462     {
463       for (i = 0; i < slots; i++)
464         if ((c = chartab_min_non_default_char (table->contents.tables + i,
465                                                default_value))
466             >= 0)
467           return c;
468     }
469   return -1;
470 }
471
472
473 /* Return the largest character whose value is not DEFAULT_VALUE in
474    TABLE.  If all characters in TABLE have DEFAULT_VALUE, return
475    -1.  */
476
477 static int
478 chartab_max_non_default_char (MSubCharTable *table, void *default_value)
479 {
480   int depth = TABLE_DEPTH (table);
481   int slots;
482   int i, c;
483
484   if (!table->contents.tables)
485     return (default_value == table->default_value
486             ? -1 : TABLE_MIN_CHAR (table) + chartab_chars[depth] - 1);
487
488   slots = chartab_slots[depth];
489
490   if (depth == CHAR_TAB_MAX_DEPTH)
491     {
492       for (i = slots - 1; i >= 0; i--)
493         if (table->contents.values[i] != default_value)
494           return (TABLE_MIN_CHAR (table) + i);
495     }
496   else
497     {
498       for (i = slots - 1; i >= 0; i--)
499         if ((c = chartab_max_non_default_char (table->contents.tables + i,
500                                                default_value))
501             >= 0)
502           return c;
503     }
504   return -1;
505 }
506
507 static void
508 free_chartable (void *object)
509 {
510   MCharTable *table = (MCharTable *) object;
511   int managedp = table->key != Mnil && table->key->managing_key;
512
513   if (table->subtable.contents.tables)
514     {
515       int i;
516
517       for (i = 0; i < chartab_slots[0]; i++)
518         free_sub_tables (table->subtable.contents.tables + i, managedp);
519       free (table->subtable.contents.tables);
520       if (managedp && table->subtable.default_value)
521         M17N_OBJECT_UNREF (table->subtable.default_value);
522     }
523   M17N_OBJECT_UNREGISTER (chartable_table, table);
524   free (object);
525 }
526
527 #include <stdio.h>
528
529 /* Support function of mdebug_dump_chartab.  */
530
531 static void
532 dump_sub_chartab (MSubCharTable *table, void *default_value,
533                   MSymbol key, int indent)
534 {
535   int depth = TABLE_DEPTH (table);
536   int min_char = TABLE_MIN_CHAR (table);
537   int max_char = min_char + (chartab_chars[depth] - 1);
538   char *prefix = (char *) alloca (indent + 1);
539   int i;
540
541   if (max_char < 0 || max_char > MCHAR_MAX)
542     max_char = MCHAR_MAX;
543
544   memset (prefix, 32, indent);
545   prefix[indent] = 0;
546
547   if (! table->contents.tables && table->default_value == default_value)
548     return;
549   fprintf (stderr, "\n%s(sub%d (U+%04X U+%04X) ",
550            prefix, depth, min_char, max_char);
551   if (key == Msymbol)
552     {
553       if (table->default_value)
554         fprintf (stderr, "(default %s)",
555                  ((MSymbol) table->default_value)->name);
556       else
557         fprintf (stderr, "(default nil)");
558     }
559   else
560     fprintf (stderr, "(default #x%X)", (unsigned) table->default_value);
561
562   default_value = table->default_value;
563   if (table->contents.tables)
564     {
565       if (depth < CHAR_TAB_MAX_DEPTH)
566         for (i = 0; i < chartab_slots[depth]; i++)
567           dump_sub_chartab (table->contents.tables + i, default_value,
568                             key, indent  + 2);
569       else
570         for (i = 0; i < chartab_slots[depth]; i++, min_char++)
571           {
572             void **val = table->contents.values + i;
573
574             if (val == default_value)
575               continue;
576             default_value = *val;
577             fprintf (stderr, "\n%s  (U+%04X", prefix, min_char);
578             while (i + 1 < chartab_slots[depth]
579                    && val[1] == default_value)
580               i++, val++, min_char++;
581             fprintf (stderr, "-U+%04X ", min_char);
582             if (key == Msymbol)
583               {
584                 if (default_value)
585                   fprintf (stderr, "%s)", ((MSymbol) default_value)->name);
586                 else
587                   fprintf (stderr, "nil)");
588               }
589             else
590               fprintf (stderr, " #xx%X)", (unsigned) default_value);
591           }
592     }
593   fprintf (stderr, ")");
594 }
595
596 \f
597 /* Internal API */
598
599 int
600 mchartable__init ()
601 {
602   chartable_table.count = 0;
603   return 0;
604 }
605
606 void
607 mchartable__fini ()
608 {
609   mdebug__report_object ("Chartable", &chartable_table);
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 @c 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 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨
667     ¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
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 @c merror_code.  */
697
698 /***ja
699     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Çʸ»ú¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹
700
701     ´Ø¿ô mchartable_lookup () ¤Ïʸ»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Çʸ»ú $C ¤Ë³ä¤ê
702     Åö¤Æ¤é¤ì¤¿ÃͤòÊÖ¤¹¡£$C ¤ËÂФ¹¤ëÌÀ¼¨Åª¤ÊÃͤ¬¤Ê¤±¤ì¤Ð¡¢$TABLE ¤Î¥Ç¥Õ¥©
703     ¥ë¥ÈÃͤòÊÖ¤¹¡£$C ¤¬ÂÅÅö¤Êʸ»ú¤Ç¤Ê¤±¤ì¤Ð¡¢mchartable_lookup () ¤Ï 
704     @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c 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 @c merror_code.  */
735
736 /***ja
737     @brief Ê¸»ú¥Æ¡¼¥Ö¥ëÃæ¤Ç¤Îʸ»ú¤ÎÃͤòÀßÄꤹ¤ë
738
739     ´Ø¿ô mchartable_set () ¤Ï¡¢Ê¸»ú¥Æ¡¼¥Ö¥ë $TABLE Ãæ¤Îʸ»ú $C ¤Ë
740     ÃÍ $VAL ¤ò³ä¤êÅö¤Æ¤ë¡£
741
742     @return
743     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchartable_set () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
744     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c 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 @c 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 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c 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 ¤ò¸Æ¤Ö¡£¤¿¤À¤·Ãͤ¬ $IGNORE ¤Ç¤¢¤ëʸ»ú¤Ë¤Ä¤¤¤Æ¤Ï´Ø¿ô¸Æ¤Ó½Ð
911     ¤·¤ò¹Ô¤Ê¤ï¤Ê¤¤¡£$IGNORE ¤Èʸ»ú¤ÎÃͤÎÈæ³Ó¤Ï @c == ¤Ç¹Ô¤Ê¤¦¤Î¤Ç¡¢Ê¸»úÎó
912     ¥ê¥Æ¥é¥ë¤ä¥Ý¥¤¥ó¥¿¤ò»È¤¦ºÝ¤Ë¤ÏÃí°Õ¤òÍפ¹¤ë¡£
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 MCharTable *
954 mdebug_dump_chartab (MCharTable *table, int indent)
955 {
956   fprintf (stderr, "(chartab (U+%04X U+%04X)",
957            table->min_char, table->max_char);
958   dump_sub_chartab (&table->subtable, table->subtable.default_value,
959                     table->key, indent + 2);
960   fprintf (stderr, ")");
961   return table;
962 }
963
964 /*** @} */
965
966 /*
967   Local Variables:
968   coding: euc-japan
969   End:
970 */