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