1 /* chartab.h -- character table module.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5 
6    This file is part of the m17n library.
7 
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12 
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17 
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301 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 
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
make_sub_tables(MSubCharTable * table,int managedp)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
make_sub_values(MSubCharTable * table,int managedp)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
free_sub_tables(MSubCharTable * table,int managedp)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
set_chartable_range(MSubCharTable * table,int from,int to,void * val,int managedp)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 *
lookup_chartable(MSubCharTable * table,int c,int * next_c,int default_p)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
map_chartable(MSubCharTable * table,void * ignore,int default_p,void (* func)(int,int,void *,void *),void * func_arg)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
chartab_min_non_default_char(MSubCharTable * table,void * default_value)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
chartab_max_non_default_char(MSubCharTable * table,void * default_value)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
free_chartable(void * object)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
dump_sub_chartab(MSubCharTable * table,void * default_value,MSymbol key,int indent)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 (mdebug__output, "\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 (mdebug__output, "(default %s)",
556 		 ((MSymbol) table->default_value)->name);
557       else
558 	fprintf (mdebug__output, "(default nil)");
559     }
560   else
561     fprintf (mdebug__output, "(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 (mdebug__output, "\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 (mdebug__output, "-U+%04X ", min_char);
583 	    if (key == Msymbol)
584 	      {
585 		if (default_value)
586 		  fprintf (mdebug__output, "%s)",
587 			   ((MSymbol) default_value)->name);
588 		else
589 		  fprintf (mdebug__output, "nil)");
590 	      }
591 	    else
592 	      fprintf (mdebug__output, " #xx%X)", (unsigned) default_value);
593 	  }
594     }
595   fprintf (mdebug__output, ")");
596 }
597 
598 
599 /* Internal API */
600 
601 int
mchartable__init()602 mchartable__init ()
603 {
604   M17N_OBJECT_ADD_ARRAY (chartable_table, "Chartable");
605   return 0;
606 }
607 
608 void
mchartable__fini()609 mchartable__fini ()
610 {
611 }
612 
613 void *
mchartable__lookup(MCharTable * table,int c,int * next_c,int default_p)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 
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 *
mchartable(MSymbol key,void * default_value)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 = -1;
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 minimum character whose value is set in a chartabe.
691 
692     The mchartable_min_char () function return the minimum character
693     whose value is set in chartable $TABLE.  No character is set its
694     value, the function returns -1.
695  */
696 
697 int
mchartable_min_char(MCharTable * table)698 mchartable_min_char (MCharTable *table)
699 {
700   return table->min_char;
701 }
702 
703 /*=*/
704 
705 /***en
706     @brief Return the maximum character whose value is set in a chartabe.
707 
708     The mchartable_max_char () function return the maximum character
709     whose value is set in chartable $TABLE.  No character is set its
710     value, the function returns -1.
711  */
712 
713 int
mchartable_max_char(MCharTable * table)714 mchartable_max_char (MCharTable *table)
715 {
716   return table->max_char;
717 }
718 
719 /*=*/
720 
721 /***en
722     @brief Return the assigned value of a character in a chartable.
723 
724     The mchartable_lookup () function returns the value assigned to
725     character $C in chartable $TABLE.  If no value has been set for $C
726     explicitly, the default value of $TABLE is returned.  If $C is not
727     a valid character, mchartable_lookup () returns @c NULL and
728     assigns an error code to the external variable #merror_code.  */
729 
730 /***ja
731     @brief ʸ���ơ��֥����ʸ���˳�����Ƥ�줿�ͤ��֤�.
732 
733     �ؿ� mchartable_lookup () ��ʸ���ơ��֥� $TABLE ���ʸ�� $C
734     �˳�����Ƥ�줿�ͤ��֤���$C ���Ф�������Ū���ͤ��ʤ���С�$TABLE
735     �Υǥե�����ͤ��֤���$C ��������ʸ���Ǥʤ���С�mchartable_lookup () ��
736     @c NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣  */
737 
738 /***
739     @errors
740     @c MERROR_CHAR
741 
742     @seealso
743     mchartable_set ()  */
744 
745 void *
mchartable_lookup(MCharTable * table,int c)746 mchartable_lookup (MCharTable *table, int c)
747 {
748   M_CHECK_CHAR (c, NULL);
749 
750   if (c < table->min_char || c > table->max_char)
751     return table->subtable.default_value;
752   return lookup_chartable (&table->subtable, c, NULL, 0);
753 }
754 
755 /*=*/
756 
757 /***en
758     @brief Assign a value to a character in a chartable.
759 
760     The mchartable_set () function sets the value of character $C in
761     chartable $TABLE to $VAL.
762 
763     @return
764     If the operation was successful, mchartable_set () returns 0.
765     Otherwise it returns -1 and assigns an error code to the external
766     variable #merror_code.  */
767 
768 /***ja
769     @brief ʸ���ơ��֥���Ǥ�ʸ�����ͤ����ꤹ��.
770 
771     �ؿ� mchartable_set () �ϡ�ʸ���ơ��֥� $TABLE ���ʸ�� $C
772     ���� $VAL �������Ƥ롣
773 
774     @return
775     ��������������С�mchartable_set () �� 0 ���֤��������Ǥʤ���� -1
776     ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣  */
777 
778 /***
779     @errors
780     @c MERROR_CHAR
781 
782     @seealso
783     mchartable_lookup (), mchartable_set_range ()  */
784 
785 
786 int
mchartable_set(MCharTable * table,int c,void * val)787 mchartable_set (MCharTable *table, int c, void *val)
788 {
789   int managedp = table->key != Mnil && table->key->managing_key;
790   MSubCharTable *sub = &table->subtable;
791   int i;
792 
793   M_CHECK_CHAR (c, -1);
794 
795   if (table->max_char < 0)
796     table->min_char = table->max_char = c;
797   else
798     {
799       if (c < table->min_char)
800 	table->min_char = c;
801       else if (c > table->max_char)
802 	table->max_char = c;
803     }
804 
805   for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++)
806     {
807       if (! sub->contents.tables)
808 	{
809 	  if (sub->default_value == val)
810 	    return 0;
811 	  make_sub_tables (sub, managedp);
812 	}
813       sub = sub->contents.tables + SUB_IDX (i, c);
814     }
815   if (! sub->contents.values)
816     {
817       if (sub->default_value == val)
818 	return 0;
819       make_sub_values (sub, managedp);
820     }
821   sub->contents.values[SUB_IDX (3, c)] = val;
822   if (managedp && val)
823     M17N_OBJECT_REF (val);
824   return 0;
825 }
826 
827 /*=*/
828 
829 /***en
830     @brief Assign a value to the characters in the specified range.
831 
832     The mchartable_set_range () function assigns value $VAL to the
833     characters from $FROM to $TO (both inclusive) in chartable $TABLE.
834 
835     @return
836     If the operation was successful, mchartable_set_range () returns
837     0.  Otherwise it returns -1 and assigns an error code to the
838     external variable #merror_code.  If $FROM is greater than $TO,
839     mchartable_set_range () returns immediately without an error.  */
840 
841 /***ja
842     @brief �����ϰϤ�ʸ�����ͤ����ꤹ��.
843 
844     �ؿ� mchartable_set_range () �ϡ�ʸ���ơ��֥� $TABLE ��� $FROM
845     ���� $TO �ޤǡ�ξü��ޤ�ˤ�ʸ���ˡ��ͤȤ��� $VAL �����ꤹ�롣
846 
847     @return
848     ��������������� mchartable_set_range () �� 0 ���֤��������Ǥʤ����
849     -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣$FROM ��
850     $TO ����礭���Ȥ��ˤϡ� mchartable_set_range ()
851     �ϲ��⤻�������顼�ⵯ�����ʤ���  */
852 
853 /***
854     @errors
855     @c MERROR_CHAR
856 
857     @seealso
858     mchartable_set ()  */
859 
860 int
mchartable_set_range(MCharTable * table,int from,int to,void * val)861 mchartable_set_range (MCharTable *table, int from, int to, void *val)
862 {
863   int managedp = table->key != Mnil && table->key->managing_key;
864 
865   M_CHECK_CHAR (from, -1);
866   M_CHECK_CHAR (to, -1);
867 
868   if (from > to)
869     return 0;
870 
871   if (table->max_char < 0)
872     table->min_char = from, table->max_char = to;
873   else{
874     if (from < table->min_char)
875       table->min_char = from;
876     if (to > table->max_char)
877       table->max_char = to;
878   }
879   set_chartable_range (&table->subtable, from, to, val, managedp);
880   return 0;
881 }
882 
883 /*=*/
884 
885 /***en
886     @brief Search for characters that have non-default value.
887 
888     The mchartable_range () function searches chartable $TABLE for the
889     first and the last character codes that do not have the default
890     value of $TABLE, and set $FROM and $TO to them, respectively.  If
891     all characters have the default value, both $FROM and $TO are set
892     to -1.  */
893 
894 /***ja
895     @brief �ͤ��ǥե���ȤȰۤʤ�ʸ����õ��.
896 
897     �ؿ� mchartable_range () ��ʸ���ơ��֥� $TABLE ��ǡ�$TABLE
898     �Υǥե�����Ͱʳ����ͤ���ĺǽ�ȺǸ��ʸ����õ�������줾��� $FROM
899     �� $TO �����ꤹ�롣���٤Ƥ�ʸ�����ͤȤ��ƥǥե�����ͤ�ȤäƤ�����ˤ�
900     $FROM �� $TO �� -1�����ꤹ�롣  */
901 
902 void
mchartable_range(MCharTable * table,int * from,int * to)903 mchartable_range (MCharTable *table, int *from, int *to)
904 {
905   *from = chartab_min_non_default_char (&table->subtable,
906 					table->subtable.default_value);
907   if (*from == -1)
908     *to = -1;
909   else
910     *to = chartab_max_non_default_char (&table->subtable,
911 					table->subtable.default_value);
912 }
913 
914 /*=*/
915 
916 /***en
917     @brief Call a function for characters in a chartable.
918 
919     The mchartable_map () function calls function $FUNC for characters
920     in chartable $TABLE.  No function call occurs for characters that
921     have value $IGNORE in $TABLE.  Comparison of $IGNORE and character
922     value is done with the operator @c ==.  Be careful when you use
923     string literals or pointers.
924 
925     Instead of calling $FUNC for each character, mchartable_map ()
926     tries to optimize the number of function calls, i.e. it makes a
927     single function call for a chunk of characters when those
928     consecutive characters have the same value.
929 
930     No matter how long the character chunk is, $FUNC is called with
931     four arguments; $FROM, $TO, $VAL, and $ARG.  $FROM and $TO (both
932     inclusive) defines the range of characters that have value $VAL.
933     $ARG is the same as $FUNC_ARG.
934 
935     @return
936     This function always returns 0.  */
937 
938 /***ja
939     @brief ʸ���ơ��֥����ʸ�����Ф��ƻ���δؿ���Ƥ�.
940 
941     �ؿ� mchartable_map () �ϡ�ʸ���ơ��֥� $TABLE ���ʸ�����Ф��ƴؿ�
942     $FUNC ��Ƥ֡�������$TABLE ��Ǥ��ͤ� $IGNORE
943     �Ǥ���ʸ���ˤĤ��Ƥϴؿ��ƤӽФ���Ԥʤ�ʤ���$IGNORE ��ʸ�����ͤ���Ӥ�
944     @c == �ǹԤʤ��Τǡ�ʸ�����ƥ���ݥ�����Ȥ��ݤˤ���դ��פ��롣
945 
946     mchartable_map () �ϡ���ʸ�����Ȥ� $FUNC
947     ��Ƥ֤ΤǤϤʤ����ؿ��ƤӽФ��β�����Ŭ�����褦�Ȥ��롣
948     ���ʤ����Ϣ³����ʸ����Ʊ���ͤ���äƤ������ˤϡ�����ʸ���ΤޤȤޤ����ΤˤĤ��ư��٤δؿ��Ƥӽ�
949     �������Ԥʤ�ʤ���
950 
951     ʸ���ΤޤȤޤ���礭���ˤ�����餺��$FUNC �� $FROM, $TO, $VAL, $ARG
952     �Σ������ǸƤФ�롣$FROM �� $TO ��ξü��ޤ�ˤ� $VAL
953     ���ͤȤ��ƻ���ʸ�����ϰϤ�����$ARG �� $FUNC_ARG ���Τ�ΤǤ��롣
954 
955     @return
956     ���δؿ��Ͼ��0���֤���  */
957 
958 int
mchartable_map(MCharTable * table,void * ignore,void (* func)(int,int,void *,void *),void * func_arg)959 mchartable_map (MCharTable *table, void *ignore,
960 		void (*func) (int, int, void *, void *),
961 		void *func_arg)
962 {
963   map_chartable (&table->subtable, ignore, 0, func, func_arg);
964   return 0;
965 }
966 
967 /*=*/
968 
969 /*** @} */
970 
971 /*** @addtogroup m17nDebug */
972 /*=*/
973 /*** @{  */
974 
975 /***en
976     @brief Dump a chartable.
977 
978     The mdebug_dump_chartab () function prints a chartable $TABLE in a
979     human readable way to the stderr or to what specified by the
980     environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
981     many columns to indent the lines but the first one.
982 
983     @return
984     This function returns $TABLE.  */
985 
986 /***ja
987     @brief ʸ���ơ��֥�����פ���.
988 
989     �ؿ� mdebug_dump_chartab () ��ʸ���ơ��֥� $TABLE ��ɸ�२�顼����
990     �⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲���
991     �ʷ��ǰ������롣$INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣
992 
993     @return
994     ���δؿ��� $TABLE ���֤���  */
995 
996 MCharTable *
mdebug_dump_chartab(MCharTable * table,int indent)997 mdebug_dump_chartab (MCharTable *table, int indent)
998 {
999   fprintf (mdebug__output, "(chartab (U+%04X U+%04X)",
1000 	   table->min_char, table->max_char);
1001   dump_sub_chartab (&table->subtable, table->subtable.default_value,
1002 		    table->key, indent + 2);
1003   fprintf (mdebug__output, ")");
1004   return table;
1005 }
1006 
1007 /*** @} */
1008 
1009 /*
1010   Local Variables:
1011   coding: euc-japan
1012   End:
1013 */
1014