1 /* plist.c -- plist 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 m17nPlist
25
26 @brief Property List objects and API for them.
27
28 A @e property @e list (or @e plist for short) is a list of zero or
29 more properties. A property consists of a @e key and a @e value,
30 where key is a symbol and value is anything that can be cast to
31 <tt>(void *)</tt>.
32
33 If the key of a property is a @e managing @e key, its @e value is
34 a @e managed @e object. A property list itself is a managed
35 objects.
36
37 If each key of a plist is one of #Msymbol, #Mtext, #Minteger, and
38 #Mplist, the plist is called as @e well-formed and represented by
39 the following notation in the documentation.
40
41 @verbatim
42 PLIST ::= '(' ELEMENT * ')'
43
44 ELEMENT ::= INTEGER | SYMBOL | M-TEXT | PLIST
45
46 M-TEXT ::= '"' text data ... '"'
47 @endverbatim
48
49 For instance, if a plist has four elements; integer -20, symbol of
50 name "sym", M-text of contents "abc", and plist of integer 10 and
51 symbol of name "another-symbol", it is represented as this:
52
53 (-20 sym "abc" (10 another-symbol))
54
55 */
56 /***ja
57 @addtogroup m17nPlist
58
59 @brief �ץ�ѥƥ��ꥹ�ȥ��֥������ȤȤ���˴ؤ��� API.
60
61 @e �ץ�ѥƥ��ꥹ�� (�ޤ��� @e plist) �� 0
62 �İʾ�Υץ�ѥƥ��Υꥹ�ȤǤ��롣�ץ�ѥƥ��� @e ���� �� @e ��
63 ����ʤ롣�����ϥ���ܥ�Ǥ��ꡢ�ͤ� <tt>(void *)</tt>
64 �˥��㥹�ȤǤ����Τʤ�в��Ǥ��ɤ���
65
66 ����ץ�ѥƥ��Υ����� @e �������� �ʤ�С����� @e �� �� @e ������
67 @e ���֥�������
68 �Ǥ��롣�ץ�ѥƥ��ꥹ�ȼ��Τ���������֥������ȤǤ��롣 */
69
70 /*=*/
71
72 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
73 /*** @addtogroup m17nInternal
74 @{ */
75
76 #include <stdio.h>
77 #include <string.h>
78 #include <ctype.h>
79
80 #include "config.h"
81 #include "m17n.h"
82 #include "m17n-misc.h"
83 #include "internal.h"
84 #include "character.h"
85 #include "mtext.h"
86 #include "symbol.h"
87 #include "plist.h"
88
89 static M17NObjectArray plist_table;
90
91 /** Set PLIST to a newly allocated plist object. */
92
93 #define MPLIST_NEW(plist) \
94 do { \
95 M17N_OBJECT (plist, free_plist, MERROR_PLIST); \
96 M17N_OBJECT_REGISTER (plist_table, plist); \
97 } while (0)
98
99
100 /** Set the element of PLIST to KEY and VAL. If PLIST is an anchor,
101 append a new anchor. */
102
103 #define MPLIST_SET(plist, key, val) \
104 do { \
105 MPLIST_KEY (plist) = (key); \
106 MPLIST_VAL (plist) = (val); \
107 if (! (plist)->next) \
108 MPLIST_NEW ((plist)->next); \
109 } while (0)
110
111
112 /** Set the element of PLIST to KEY and VAL. PLIST must be an anchor.
113 Append a new anchor and set PLIST to that anchor. */
114
115 #define MPLIST_SET_ADVANCE(plist, key, val) \
116 do { \
117 MPLIST_KEY (plist) = (key); \
118 MPLIST_VAL (plist) = (val); \
119 MPLIST_NEW ((plist)->next); \
120 plist = (plist)->next; \
121 } while (0)
122
123
124 static void
free_plist(void * object)125 free_plist (void *object)
126 {
127 MPlist *plist = (MPlist *) object;
128
129 do {
130 MPlist *next = plist->next;
131
132 if (MPLIST_KEY (plist) != Mnil
133 && MPLIST_KEY (plist)->managing_key)
134 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
135 M17N_OBJECT_UNREGISTER (plist_table, plist);
136 free (plist);
137 plist = next;
138 } while (plist && plist->control.ref_count == 1);
139 M17N_OBJECT_UNREF (plist);
140 }
141
142
143
144 /* Load a plist from a string. */
145
146 #define READ_CHUNK 0x10000
147
148 typedef struct
149 {
150 /* File pointer if the stream is associated with a file. Otherwise
151 NULL. */
152 FILE *fp;
153 int eof;
154 unsigned char buffer[READ_CHUNK];
155 unsigned char *p, *pend;
156 } MStream;
157
158 static int
get_byte(MStream * st)159 get_byte (MStream *st)
160 {
161 int n;
162
163 if (! st->fp || st->eof)
164 return EOF;
165 n = fread (st->buffer, 1, READ_CHUNK, st->fp);
166 if (n <= 0)
167 {
168 st->eof = 1;
169 return EOF;
170 }
171 st->p = st->buffer + 1;
172 st->pend = st->buffer + n;
173 return st->buffer[0];
174 }
175
176 #define GETC(st) ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
177
178 #define UNGETC(c, st) (--((st)->p))
179
180 /** Mapping table for reading a number. Hexadecimal chars
181 (0..9,A..F,a..F) are mapped to the corresponding numbers.
182 Apostrophe (code 39) is mapped to 254. All the other bytes are
183 mapped to 255. */
184 unsigned char hex_mnemonic[256];
185
186 /** Mapping table for escaped characters. Mnemonic characters (e, b,
187 f, n, r, or t) that follows '\' are mapped to the corresponding
188 character code. All the other bytes are mapped to themselves. */
189 unsigned char escape_mnemonic[256];
190
191
192 /** Read an integer from the stream ST. It is assumed that we have
193 already read one character C. */
194
195 static int
read_decimal(MStream * st,int c)196 read_decimal (MStream *st, int c)
197 {
198 int num = 0;
199
200 while (c >= '0' && c <= '9')
201 {
202 num = (num * 10) + (c - '0');
203 c = GETC (st);
204 }
205
206 if (c != EOF)
207 UNGETC (c, st);
208 return num;
209 }
210
211 /** Read an unsigned from the stream ST. */
212
213 static unsigned
read_hexadesimal(MStream * st)214 read_hexadesimal (MStream *st)
215 {
216 int c;
217 unsigned num = 0, n;
218
219 while ((c = GETC (st)) != EOF
220 && (n = hex_mnemonic[c]) < 16)
221 num = (num << 4) | n;
222 if (c != EOF)
223 UNGETC (c, st);
224 return num;
225 }
226
227
228 /** Read an M-text element from ST, and add it to LIST. Return a list
229 for the next element. */
230
231 #define READ_MTEXT_BUF_SIZE 256
232
233 static MPlist *
read_mtext_element(MPlist * plist,MStream * st,int skip)234 read_mtext_element (MPlist *plist, MStream *st, int skip)
235 {
236 unsigned char buffer[READ_MTEXT_BUF_SIZE], *buf = buffer;
237 int nbytes = READ_MTEXT_BUF_SIZE;
238 int c, i;
239
240 i = 0;
241 while ((c = GETC (st)) != EOF && c != '"')
242 {
243 int is_char = 0;
244
245 if (c == '\\')
246 {
247 c = GETC (st);
248 if (c == EOF)
249 break;
250 if (c == '\n')
251 continue;
252 if (c == 'x' || c == 'u')
253 {
254 int next_c;
255
256 c = read_hexadesimal (st);
257 next_c = GETC (st);
258 if (next_c != ' ')
259 UNGETC (next_c, st);
260 if (c >= 0x80)
261 is_char = 1;
262 }
263 else
264 c = escape_mnemonic[c];
265 }
266
267 if (! skip)
268 {
269 if (i + MAX_UTF8_CHAR_BYTES + 1 >= nbytes)
270 {
271 if (buf == buffer)
272 {
273 nbytes *= 2;
274 buf = malloc (nbytes);
275 memcpy (buf, buffer, i);
276 }
277 else
278 {
279 nbytes += READ_MTEXT_BUF_SIZE;
280 buf = realloc (buf, nbytes);
281 }
282 }
283
284 if (is_char)
285 i += CHAR_STRING_UTF8 (c, buf);
286 else
287 buf[i++] = c;
288 }
289 }
290
291 if (! skip)
292 {
293 MText *mt;
294
295 buf[i] = 0;
296 mt = mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, (buf == buffer));
297 if (buf != buffer)
298 mt->allocated = nbytes;
299 MPLIST_SET_ADVANCE (plist, Mtext, mt);
300 }
301 return plist;
302 }
303
304 static int
read_character(MStream * st,int c)305 read_character (MStream *st, int c)
306 {
307 unsigned char buf[MAX_UTF8_CHAR_BYTES + 1];
308 int len = CHAR_BYTES_BY_HEAD (c);
309 int i;
310
311 buf[0] = c;
312 for (i = 1; i < len; i++)
313 {
314 c = GETC (st);
315 if (c == EOF
316 || (c & 0xC0) != 0x80)
317 break;
318 buf[i] = c;
319 }
320 if (i == len)
321 c = STRING_CHAR_UTF8 (buf);
322 else
323 c = buf[0];
324 return c;
325 }
326
327
328 /** Read a symbol element from ST, and add it to LIST. Return a list
329 for the next element. */
330
331 static MPlist *
read_symbol_element(MPlist * plist,MStream * st,int c,int skip)332 read_symbol_element (MPlist *plist, MStream *st, int c, int skip)
333 {
334 unsigned char buffer[1024];
335 int bufsize = 1024;
336 unsigned char *buf = buffer;
337 int i;
338
339 i = 0;
340 while (c != EOF
341 && c > ' '
342 && c != ')' && c != '(' && c != '"')
343 {
344 if (i >= bufsize)
345 {
346 bufsize *= 2;
347 if (buf == buffer)
348 {
349 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
350 memcpy (buf, buffer, i);
351 }
352 else
353 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
354 }
355 if (c == '\\')
356 {
357 c = GETC (st);
358 if (c == EOF)
359 break;
360 c = escape_mnemonic[c];
361 }
362 if (! skip)
363 buf[i++] = c;
364 c = GETC (st);
365 }
366
367 if (c > ' ')
368 UNGETC (c, st);
369 if (! skip)
370 {
371 buf[i] = 0;
372 MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
373 if (buf != buffer)
374 free (buf);
375 }
376 return plist;
377 }
378
379 /** Read an integer element from ST, and add it to LIST. Return a
380 list for the next element. It is assumed that we have already
381 read the character C. */
382
383 static MPlist *
read_integer_element(MPlist * plist,MStream * st,int c,int skip)384 read_integer_element (MPlist *plist, MStream *st, int c, int skip)
385 {
386 int num;
387
388 if (c == '#')
389 {
390 c = GETC (st);
391 if (c != 'x')
392 {
393 UNGETC (c, st);
394 return read_symbol_element (plist, st, '#', skip);
395 }
396 num = read_hexadesimal (st);
397 }
398 else if (c == '0')
399 {
400 c = GETC (st);
401 num = (c == 'x' ? read_hexadesimal (st) : read_decimal (st, c));
402 }
403 else if (c == '?')
404 {
405 c = GETC (st);
406 if (c == EOF)
407 num = 0;
408 else if (c != '\\')
409 {
410 if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
411 num = c;
412 else
413 num = read_character (st, c);
414 }
415 else
416 {
417 c = GETC (st);
418 if (c == EOF)
419 num = '\\';
420 else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
421 num = escape_mnemonic[c];
422 else
423 num = read_character (st, c);
424 }
425 }
426 else if (c == '-')
427 {
428 c = GETC (st);
429 if (c < '0' || c > '9')
430 {
431 UNGETC (c, st);
432 return read_symbol_element (plist, st, '-', skip);
433 }
434 num = - read_decimal (st, c);
435 }
436 else
437 num = read_decimal (st, c);
438
439 if (! skip)
440 MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
441 return plist;
442 }
443
444 /* Read an element of various type from stream ST, and add it to LIST.
445 Return a list for the next element. The element type is decided by
446 the first token character found as below:
447 '(': plist
448 '"': mtext
449 '0'..'9', '-': integer
450 '?': integer representing character code
451 the other ASCII letters: symbol
452
453 If KEYS is not NULL, it is a plist contains target keys and stop
454 keys. In this caes, read only a plist whose key has value 1 in
455 KEYS, and return NULL when we encounter a plist whose key has value
456 0 in KEYS while skipping any other elements. */
457
458 static MPlist *
read_element(MPlist * plist,MStream * st,MPlist * keys)459 read_element (MPlist *plist, MStream *st, MPlist *keys)
460 {
461 int c;
462
463 /* Skip separators and comments. */
464 while (1)
465 {
466 while ((c = GETC (st)) != EOF && c <= ' ');
467 if (c != ';')
468 break;
469 while ((c = GETC (st)) != EOF && c != '\n');
470 if (c == EOF)
471 break;
472 }
473
474 if (c == '(')
475 {
476 MPlist *pl, *p;
477
478 MPLIST_NEW (pl);
479 p = pl;
480 p = read_element (p, st, NULL);
481 if (keys && p && MPLIST_SYMBOL_P (pl))
482 {
483 if (MPLIST_TAIL_P (keys))
484 {
485 while ((p = read_element (p, st, NULL)));
486 MPLIST_SET_ADVANCE (plist, Mplist, pl);
487 return NULL;
488 }
489 else
490 {
491 MPlist *p0 = keys;
492
493 MPLIST_FIND (p0, MPLIST_SYMBOL (pl));
494 if (! MPLIST_TAIL_P (p0) && ! MPLIST_VAL (p0))
495 {
496 M17N_OBJECT_UNREF (pl);
497 return NULL;
498 }
499 while ((p = read_element (p, st, NULL)));
500 if (! MPLIST_TAIL_P (p0))
501 {
502 MPLIST_SET_ADVANCE (plist, Mplist, pl);
503 return NULL;
504 }
505 else
506 M17N_OBJECT_UNREF (pl);
507 }
508 }
509 else
510 {
511 if (p)
512 while ((p = read_element (p, st, NULL)));
513 MPLIST_SET_ADVANCE (plist, Mplist, pl);
514 }
515 return plist;
516 }
517 if (c == '"')
518 return (read_mtext_element (plist, st, keys ? 1 : 0));
519 if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
520 return (read_integer_element (plist, st, c, keys ? 1 : 0));
521 if (c == EOF || c == ')')
522 return NULL;
523 return (read_symbol_element (plist, st, c, keys ? 1 : 0));
524 }
525
526 #define PUTC(MT, C) \
527 do { \
528 if (MT) \
529 mtext_cat_char ((MT), (C)); \
530 else \
531 putc ((C), mdebug__output); \
532 } while (0);
533
534 #define PUTS(MT, STR) \
535 do { \
536 if (MT) \
537 MTEXT_CAT_ASCII ((MT), (STR)); \
538 else \
539 fputs ((STR), mdebug__output); \
540 } while (0)
541
542
543 static void
write_symbol(MText * mt,MSymbol sym)544 write_symbol (MText *mt, MSymbol sym)
545 {
546 if (sym == Mnil)
547 {
548 PUTS (mt, "nil");
549 }
550 else
551 {
552 char *name = MSYMBOL_NAME (sym);
553
554 if (isdigit (*name))
555 PUTC (mt, '\\');
556 while (*name)
557 {
558 if (*name <= ' ' || *name == '\\' || *name == '"'
559 || *name == '(' || *name == ')')
560 PUTC (mt, '\\');
561 PUTC (mt, *name);
562 name++;
563 }
564 }
565 }
566
567 static void
write_element(MText * mt,MPlist * plist,int indent)568 write_element (MText *mt, MPlist *plist, int indent)
569 {
570 if (MPLIST_SYMBOL_P (plist))
571 {
572 write_symbol (mt, MPLIST_SYMBOL (plist));
573 }
574 else if (MPLIST_INTEGER_P (plist))
575 {
576 int num = MPLIST_INTEGER (plist);
577 char buf[128];
578
579 sprintf (buf, "%d", num);
580 PUTS (mt, buf);
581 }
582 else if (MPLIST_PLIST_P (plist)
583 || MPLIST_NESTED_P (plist))
584 {
585 MPlist *pl;
586 int newline = 0;
587
588 if (MPLIST_NESTED_P (plist))
589 {
590 write_symbol (mt, MPLIST_KEY (plist));
591 PUTC (mt, ':');
592 }
593 plist = MPLIST_PLIST (plist);
594 PUTC (mt, '(');
595 if (indent >= 0)
596 indent++;
597 MPLIST_DO (pl, plist)
598 {
599 if (pl != plist)
600 {
601 if (indent > 0 && (MPLIST_PLIST_P (pl) || MPLIST_MTEXT_P (pl)))
602 newline = 1;
603 if (newline)
604 {
605 int i;
606
607 PUTC (mt, '\n');
608 for (i = 1; i < indent; i++)
609 PUTC (mt, ' ');
610 }
611 PUTC (mt, ' ');
612 }
613 write_element (mt, pl, indent);
614 if (indent >= 0)
615 newline = (MPLIST_PLIST_P (pl) || MPLIST_MTEXT_P (pl));
616 }
617 PUTC (mt, ')');
618 }
619 else if (MPLIST_MTEXT_P (plist))
620 {
621 MText *this_mt = MPLIST_MTEXT (plist);
622 int from = 0, to = mtext_nchars (this_mt);
623 int stop1 = 0, stop2 = 0;
624
625 if (! mt && this_mt->format > MTEXT_FORMAT_UTF_8)
626 {
627 this_mt = mtext_dup (this_mt);
628 mtext__adjust_format (this_mt, MTEXT_FORMAT_UTF_8);
629 }
630
631 PUTC (mt, '"');
632 while (1)
633 {
634 int stop, escaped;
635
636 if (from == stop1)
637 {
638 if ((stop1 = mtext_character (this_mt, from, to, '"')) < 0)
639 stop1 = to;
640 }
641 if (from == stop2)
642 {
643 if ((stop2 = mtext_character (this_mt, from, to, '\\')) < 0)
644 stop2 = to;
645 }
646 if (stop1 < stop2)
647 stop = stop1++, escaped = '"';
648 else
649 stop = stop2++, escaped = '\\';
650 if (mt)
651 mtext_copy (mt, mtext_nchars (mt), this_mt, from, stop);
652 else
653 {
654 unsigned char *data = MTEXT_DATA (this_mt);
655 unsigned char *beg = data + mtext__char_to_byte (this_mt, from);
656 unsigned char *end = data + mtext__char_to_byte (this_mt, stop);
657
658 while (beg < end)
659 putc (*beg, mdebug__output), beg++;
660 }
661 if (stop == to)
662 break;
663 PUTC (mt, '\\');
664 PUTC (mt, escaped);
665 from = stop + 1;
666 }
667 PUTC (mt, '"');
668 if (this_mt != MPLIST_MTEXT (plist))
669 M17N_OBJECT_UNREF (this_mt);
670 }
671 else if (MPLIST_STRING_P (plist))
672 {
673 char *str = MPLIST_STRING (plist);
674
675 if (mt)
676 {
677 MText *this_mt = mtext__from_data (str, strlen (str),
678 MTEXT_FORMAT_UTF_8, 0);
679
680 mtext_copy (mt, mtext_nchars (mt),
681 this_mt, 0, mtext_nchars (this_mt));
682 M17N_OBJECT_UNREF (this_mt);
683 }
684 else
685 fprintf (mdebug__output, "%s", str);
686 }
687 else
688 {
689 char buf[128];
690
691 write_symbol (mt, MPLIST_KEY (plist));
692 PUTC (mt, ':');
693 sprintf (buf, "%04X", (unsigned) MPLIST_VAL (plist));
694 PUTS (mt, buf);
695 }
696 }
697
698
699 /* Internal API */
700 int
mplist__init()701 mplist__init ()
702 {
703 int i;
704
705 M17N_OBJECT_ADD_ARRAY (plist_table, "Plist");
706
707 Minteger = msymbol ("integer");
708 Mplist = msymbol_as_managing_key ("plist");
709 Mtext = msymbol_as_managing_key ("mtext");
710
711 for (i = 0; i < 256; i++)
712 hex_mnemonic[i] = 255;
713 for (i = '0'; i <= '9'; i++)
714 hex_mnemonic[i] = i - '0';
715 for (i = 'A'; i <= 'F'; i++)
716 hex_mnemonic[i] = i - 'A' + 10;
717 for (i = 'a'; i <= 'f'; i++)
718 hex_mnemonic[i] = i - 'a' + 10;
719 for (i = 0; i < 256; i++)
720 escape_mnemonic[i] = i;
721 escape_mnemonic['e'] = 27;
722 escape_mnemonic['b'] = '\b';
723 escape_mnemonic['f'] = '\f';
724 escape_mnemonic['n'] = '\n';
725 escape_mnemonic['r'] = '\r';
726 escape_mnemonic['t'] = '\t';
727 escape_mnemonic['\\'] = '\\';
728
729 return 0;
730 }
731
732 void
mplist__fini(void)733 mplist__fini (void)
734 {
735 }
736
737
738 /* Parse this form of PLIST:
739 (symbol:KEY1 TYPE1:VAL1 symbol:KEY2 TYPE2:VAL2 ...)
740 and return a newly created plist of this form:
741 (KEY1:VAL1 KEY2:VAL2 ...) */
742
743 MPlist *
mplist__from_plist(MPlist * plist)744 mplist__from_plist (MPlist *plist)
745 {
746 MPlist *pl, *p;
747
748 MPLIST_NEW (pl);
749 p = pl;
750 while (! MPLIST_TAIL_P (plist))
751 {
752 MSymbol key, type;
753
754 if (! MPLIST_SYMBOL_P (plist))
755 MERROR (MERROR_PLIST, NULL);
756 key = MPLIST_SYMBOL (plist);
757 plist = MPLIST_NEXT (plist);
758 type = MPLIST_KEY (plist);
759 if (type->managing_key && MPLIST_VAL (plist))
760 M17N_OBJECT_REF (MPLIST_VAL (plist));
761 if (type == Mplist)
762 MPLIST_SET_NESTED_P (p);
763 MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
764 plist = MPLIST_NEXT (plist);
765 }
766 return pl;
767 }
768
769 /** Parse this form of PLIST:
770 ((symbol:KEY1 ANY:VAL1 ... ) (symbol:KEY2 ANY:VAL2 ...) ...)
771 and return a newly created plist of this form:
772 (KEY1:(ANY:VAL1 ...) KEY2:(ANY:VAL2 ...) ...)
773 ANY can be any type. */
774
775 MPlist *
mplist__from_alist(MPlist * plist)776 mplist__from_alist (MPlist *plist)
777 {
778 MPlist *pl, *p;
779
780 MPLIST_NEW (pl);
781 p = pl;
782 MPLIST_DO (plist, plist)
783 {
784 MPlist *elt;
785
786 if (! MPLIST_PLIST_P (plist))
787 MERROR (MERROR_PLIST, NULL);
788 elt = MPLIST_PLIST (plist);
789 if (! MPLIST_SYMBOL_P (elt))
790 MERROR (MERROR_PLIST, NULL);
791 MPLIST_SET_NESTED_P (p);
792 MPLIST_SET_ADVANCE (p, MPLIST_SYMBOL (elt), MPLIST_NEXT (elt));
793 M17N_OBJECT_REF (MPLIST_NEXT (elt));
794 }
795 return pl;
796 }
797
798
799 MPlist *
mplist__from_file(FILE * fp,MPlist * keys)800 mplist__from_file (FILE *fp, MPlist *keys)
801 {
802 MPlist *plist, *pl;
803 MStream st;
804
805 st.fp = fp;
806 st.eof = 0;
807 st.p = st.pend = st.buffer;
808 MPLIST_NEW (plist);
809 pl = plist;
810 while ((pl = read_element (pl, &st, keys)));
811 return plist;
812 }
813
814
815 /** Parse $STR of $N bytes and return a property list object. $FORMAT
816 must be either @c MTEXT_FORMAT_US_ASCII or @c MTEXT_FORMAT_UTF_8,
817 and controls how to produce @c STRING or @c M-TEXT in the
818 following definition.
819
820 The syntax of $STR is as follows.
821
822 PLIST ::= '(' ELEMENT * ')'
823
824 ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST
825
826 SYMBOL ::= ascii-character-sequence
827
828 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
829
830 UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
831
832 M-TEXT ::= '"' byte-sequence '"'
833
834 Each kind of @c ELEMENT is assigned one of these keys:
835 @c Msymbol, @c Mint, @c Munsigned, @c Mtext, @c Mplist
836
837 In an ascii-character-sequence, a backslush (\) is used as the escape
838 character, which means that, for instance, <tt>"abc\ def"</tt>
839 produces a symbol whose name is of length seven with the fourth
840 character being a space.
841
842 In a byte-sequence, "\r", "\n", "\e", and "\t" are replaced by CR,
843 NL, ESC, and TAB character respectively, "\xXX" are replaced by
844 byte 0xXX. After this replacement, the byte-sequence is decoded
845 into M-TEXT by $CODING. */
846
847 MPlist *
mplist__from_string(unsigned char * str,int n)848 mplist__from_string (unsigned char *str, int n)
849 {
850 MPlist *plist, *pl;
851 MStream st;
852
853 st.fp = NULL;
854 st.eof = 0;
855 st.p = str;
856 st.pend = str + n;
857 MPLIST_NEW (plist);
858 pl = plist;
859 while ((pl = read_element (pl, &st, NULL)));
860 return plist;
861 }
862
863 int
mplist__serialize(MText * mt,MPlist * plist,int pretty)864 mplist__serialize (MText *mt, MPlist *plist, int pretty)
865 {
866 MPlist *pl;
867 int separator = pretty ? '\n' : ' ';
868
869 MPLIST_DO (pl, plist)
870 {
871 if (pl != plist)
872 mtext_cat_char (mt, separator);
873 write_element (mt, pl, pretty ? 0 : -1);
874 }
875 if (pretty)
876 mtext_cat_char (mt, separator);
877 return 0;
878 }
879
880 /**en
881 @brief Concatenate two plists.
882
883 The mplist__conc () function concatenates plist $TAIL at the end of
884 plist $PLIST and return $PLIST. If $TAIL is empty, return $PLIST
885 without modifying it. */
886
887 MPlist *
mplist__conc(MPlist * plist,MPlist * tail)888 mplist__conc (MPlist *plist, MPlist *tail)
889 {
890 MPlist *pl;
891
892 if (MPLIST_TAIL_P (tail))
893 return plist;
894 MPLIST_DO (pl, plist);
895 MPLIST_KEY (pl) = MPLIST_KEY (tail);
896 MPLIST_VAL (pl) = MPLIST_VAL (tail);
897 if (MPLIST_KEY (pl)->managing_key && MPLIST_VAL (pl))
898 M17N_OBJECT_REF (MPLIST_VAL (pl));
899 if (MPLIST_NESTED_P (tail))
900 MPLIST_SET_NESTED_P (pl);
901 tail = MPLIST_NEXT (tail);
902 MPLIST_NEXT (pl) = tail;
903 M17N_OBJECT_REF (tail);
904 return plist;
905 }
906
907 /*=*/
908 /**en
909 @brief Discard a property at the beginning of a property list.
910
911 The mplist__pop_unref () function removes a property at the
912 beginning of property list $PLIST, and if the property value is a
913 managed object, unref it. As a result, the second key and value
914 of the original $PLIST become the first of those of the new
915 $PLIST. */
916
917 void
mplist__pop_unref(MPlist * plist)918 mplist__pop_unref (MPlist *plist)
919 {
920 MSymbol key;
921 void *val;
922
923 if (MPLIST_TAIL_P (plist))
924 return;
925 key = MPLIST_KEY (plist);
926 val = mplist_pop (plist);
927 if (key->managing_key)
928 M17N_OBJECT_UNREF (val);
929 }
930
931 /**en
932 @brief Search for an element of an alist represented by a plist.
933
934 The mplist__assq () function treats $PLIST as an association list
935 (elements are plists (key is #Mplist) whose first element is a
936 symbol (key is #Msymbol)), and find an element whose first element
937 has key #Msymbol and value $KEY.
938
939 Non-plist elements of $PLIST are ignored.
940
941 @return
942 This function returns a found element or NULL if no element
943 matches with $KEY. */
944
945 MPlist *
mplist__assq(MPlist * plist,MSymbol key)946 mplist__assq (MPlist *plist, MSymbol key)
947 {
948 MPLIST_DO (plist, plist)
949 if (MPLIST_PLIST_P (plist))
950 {
951 MPlist *pl = MPLIST_PLIST (plist);
952
953 if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == key)
954 return plist;
955 }
956 return NULL;
957 }
958
959 /*** @} */
960 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
961
962
963 /* External API */
964
965 /*** @addtogroup m17nPlist */
966 /*** @{ */
967 /*=*/
968
969 /***en
970 @brief Symbol whose name is "integer".
971
972 The symbol @c Minteger has the name <tt>"integer"</tt>. The value
973 of a property whose key is @c Minteger must be an integer. */
974 /***ja
975 @brief "integer" ��̾���Ȥ��ƻ��ĥ���ܥ�.
976
977 ����ܥ� @c Minteger �� <tt>"integer"</tt> �Ȥ���̾������ġ�������
978 @c Minteger �Ǥ���ץ�ѥƥ����ͤ������ͤǤʤ��ƤϤʤ�ʤ��� */
979
980 MSymbol Minteger;
981 /*=*/
982
983 /***en
984 @brief Symbol whose name is "plist".
985
986 The symbol @c Mplist has the name <tt>"plist"</tt>. It is a
987 managing key. A value of a property whose key is @c Mplist must
988 be a plist. */
989 /***ja
990 @brief "plist" ��̾���Ȥ��ƻ��ĥ���ܥ�.
991
992 ����ܥ� @c Mplist �� <tt>"plist"</tt>
993 �Ȥ���̾������ġ�����ϴ��������Ǥ��롣������ @c Mplist
994 �Ǥ���ץ�ѥƥ����ͤ� plist �Ǥʤ��ƤϤʤ�ʤ��� */
995
996 MSymbol Mplist;
997 /*=*/
998
999 /***en
1000 @brief Symbol whose name is "mtext".
1001
1002 The symbol @c Mtext has the name <tt>"mtext"</tt>. It is a
1003 managing key. A value of a property whose key is @c Mtext must be an
1004 M-text. */
1005
1006 /***ja
1007 @brief "mtext" ��̾���Ȥ��ƻ��ĥ���ܥ�.
1008
1009 ����ܥ� @c Mtext �� <tt>"mtext"</tt>
1010 �Ȥ���̾������Ĵ��������Ǥ��롣������ @c Mtext
1011 �Ǥ���ץ�ѥƥ����ͤ� M-text �Ǥʤ��ƤϤʤ�ʤ��� */
1012
1013 MSymbol Mtext;
1014
1015 /*=*/
1016 /***en
1017 @brief Create a property list object.
1018
1019 The mplist () function returns a newly created property list
1020 object of length zero.
1021
1022 @returns
1023 This function returns a newly created property list.
1024
1025 @errors
1026 This function never fails. */
1027 /***ja
1028 @brief �ץ�ѥƥ��ꥹ�ȥ��֥������Ȥ���.
1029
1030 �ؿ� mplist () ��Ĺ�� 0 �Υץ�ѥƥ��ꥹ�ȥ��֥������Ȥ�����ä��֤���
1031
1032 @returns
1033 ���δؿ��Ͽ��������줿�ץ�ѥƥ��ꥹ�ȥ��֥������Ȥ��֤���
1034
1035 @errors
1036 ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */
1037
1038 MPlist *
mplist(void)1039 mplist (void)
1040 {
1041 MPlist *plist;
1042
1043 MPLIST_NEW (plist);
1044 return plist;
1045 }
1046
1047 /*=*/
1048 /***en
1049 @brief Copy a property list.
1050
1051 The mplist_copy () function copies property list $PLIST. In the
1052 copy, the values are the same as those of $PLIST.
1053
1054 @return
1055 This function returns a newly created plist which is a copy of
1056 $PLIST.
1057
1058 @errors
1059 This function never fails. */
1060 /***ja
1061 @brief �ץ�ѥƥ��ꥹ�Ȥԡ�����.
1062
1063 �ؿ� mplist_copy () �ϥץ�ѥƥ��ꥹ�� $PLIST
1064 �ԡ����롣���ԡ��Τ��٤Ƥ��ͤϥ��ԡ��� $PLIST ���ͤ�Ʊ���Ǥ��롣
1065
1066 @return
1067 ���δؿ��Ͽ��������줿��$PLIST �Υ��ԡ��Ǥ���ץ�ѥƥ��ꥹ�Ȥ��֤���
1068
1069 @errors
1070 ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */
1071
1072 MPlist *
mplist_copy(MPlist * plist)1073 mplist_copy (MPlist *plist)
1074 {
1075 MPlist *copy = mplist (), *pl = copy;
1076
1077 MPLIST_DO (plist, plist)
1078 {
1079 if (MPLIST_NESTED_P (plist))
1080 MPLIST_SET_NESTED_P (pl);
1081 pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist));
1082 }
1083 return copy;
1084 }
1085
1086 /*=*/
1087
1088 /***en
1089 @brief Set the value of a property in a property list.
1090
1091 The mplist_put () function searches property list $PLIST
1092 from the beginning for a property whose key is $KEY. If such a
1093 property is found, its value is changed to $VALUE. Otherwise, a
1094 new property whose key is $KEY and value is $VALUE is appended at
1095 the end of $PLIST. See the documentation of mplist_add () for
1096 the restriction on $KEY and $VAL.
1097
1098 If $KEY is a managing key, $VAL must be a managed object. In this
1099 case, the reference count of the old value, if not @c NULL, is
1100 decremented by one, and that of $VAL is incremented by one.
1101
1102 @return
1103 If the operation was successful, mplist_put () returns a sublist of
1104 $PLIST whose first element is the just modified or added one.
1105 Otherwise, it returns @c NULL. */
1106 /***ja
1107 @brief �ץ�ѥƥ��ꥹ����Υץ�ѥƥ����ͤ����ꤹ��.
1108
1109 �ؿ� mplist_put () �ϥץ�ѥƥ��ꥹ�� $PLIST ��Ϥᤫ��õ���ơ�������
1110 $KEY �Ǥ���ץ�ѥƥ��Ĥ��롣���Ĥ���С������ͤ� $VALUE
1111 ���ѹ����롣���Ĥ���ʤ���С������� $KEY ���ͤ� $VALUE
1112 �Ǥ��뿷�����ץ�ѥƥ��� $PLIST ���������ɲä���롣$KEY �� $VAL
1113 ���Ф������¤ˤĤ��Ƥϡ�mplist_add () �������ȡ�
1114
1115 $KEY �����������ʤ�С�
1116 $VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢�Ť��ͤλ��ȿ���
1117 @c NULL �Ǥʤ���� 1 ���餵�졢$VAL �λ��ȿ��� 1 ���䤵��롣
1118
1119 @return
1120 ��������������� mplist_put () ���ѹ����줿���ɲä��줿���Ǥ���Ϥޤ�
1121 $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */
1122
1123 MPlist *
mplist_put(MPlist * plist,MSymbol key,void * val)1124 mplist_put (MPlist *plist, MSymbol key, void *val)
1125 {
1126 if (key == Mnil)
1127 MERROR (MERROR_PLIST, NULL);
1128 MPLIST_FIND (plist, key);
1129 if (key->managing_key)
1130 {
1131 if (! MPLIST_TAIL_P (plist))
1132 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1133 if (val)
1134 M17N_OBJECT_REF (val);
1135 }
1136 MPLIST_SET (plist, key, val);
1137 return plist;
1138 }
1139
1140 /*=*/
1141
1142 /***en
1143 @brief Get the value of a property in a property list.
1144
1145 The mplist_get () function searches property list $PLIST from the
1146 beginning for a property whose key is $KEY. If such a property is
1147 found, its value is returned as the type of <tt>(void *)</tt>. If
1148 not found, @c NULL is returned.
1149
1150 When @c NULL is returned, there are two possibilities: one is the
1151 case where no property is found (see above); the other is the case
1152 where a property is found and its value is @c NULL. In case that
1153 these two cases must be distinguished, use the mplist_find_by_key ()
1154 function. */
1155 /***ja
1156 @brief �ץ�ѥƥ��ꥹ����Υץ�ѥƥ����ͤ�����.
1157
1158 �ؿ� mplist_get () �ϡ��ץ�ѥƥ��ꥹ�� $PLIST ��Ϥᤫ��õ���ơ�����
1159 �� $KEY �Ǥ���ץ�ѥƥ��Ĥ��롣���Ĥ���С������ͤ�
1160 <tt>(void *)</tt> �����֤������Ĥ���ʤ���� @c NULL ���֤���
1161
1162 @c NULL ���֤ä��ݤˤ���Ĥβ�ǽ��������:
1163 �嵭�Τ褦�˥ץ�ѥƥ������Ĥ���ʤ��ä����ȡ��ץ�ѥƥ������Ĥ��ꡢ�����ͤ�
1164 @c NULL �Ǥ�����Ǥ��롣��������̤���ɬ�פ�������ˤϴؿ�
1165 mplist_find_by_key () ��Ȥ����ȡ� */
1166
1167 /***
1168 @seealso
1169 mplist_find_by_key () */
1170
1171 void *
mplist_get(MPlist * plist,MSymbol key)1172 mplist_get (MPlist *plist, MSymbol key)
1173 {
1174 MPLIST_FIND (plist, key);
1175 return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
1176 }
1177
1178 /*=*/
1179
1180 /***en
1181 @brief Set the value (function pointer) of a property in a property list.
1182
1183 The mplist_put_func () function is similar to mplist_put () but for
1184 setting function pointer $FUNC in property list $PLIST for key
1185 $KEY. $KEY must not be a managing key. */
1186
1187 /***ja
1188 @brief �ץ�ѥƥ��ꥹ����Υץ�ѥƥ��˴ؿ��ݥ��Ǥ����ͤ����ꤹ��.
1189
1190 �ؿ� mplist_put_func () �ϴؿ� mplist_put () Ʊ�͡��ץ�ѥƥ��ꥹ�� $PLIST
1191 ��ǥ����� $KEY �Ǥ���ץ�ѥƥ����ͤ����ꤹ�롣â�������ͤϴؿ��ݥ���
1192 $FUNC �Ǥ��롣$KEY �ϴ��������Ǥ��äƤϤʤ�ʤ��� */
1193
1194
1195 /***
1196 @seealso
1197 mplist_put (), M17N_FUNC () */
1198
1199 MPlist *
mplist_put_func(MPlist * plist,MSymbol key,M17NFunc func)1200 mplist_put_func (MPlist *plist, MSymbol key, M17NFunc func)
1201 {
1202 if (key == Mnil || key->managing_key)
1203 MERROR (MERROR_PLIST, NULL);
1204 MPLIST_FIND (plist, key);
1205 MPLIST_KEY (plist) = key;
1206 MPLIST_FUNC (plist) = func;
1207 MPLIST_SET_VAL_FUNC_P (plist);
1208 if (! plist->next)
1209 MPLIST_NEW ((plist)->next);
1210 return plist;
1211 }
1212
1213 /*=*/
1214
1215 /***en
1216 @brief Get the value (function pointer) of a property in a property list.
1217
1218 The mplist_get_func () function is similar to mplist_get () but for
1219 getting a function pointer from property list $PLIST by key $KEY. */
1220
1221 /***ja
1222 @brief �ץ�ѥƥ��ꥹ�Ȥ���ץ�ѥƥ��δؿ��ݥ��Ǥ����ͤ�����.
1223
1224 �ؿ� mplist_get_func () �ϴؿ� mplist_get () ��Ʊ�ͤˡ��ץ�ѥƥ���
1225 ���� $PLIST ��ǥ����� $KEY �Ǥ���ץ�ѥƥ����͡�â���ؿ��ݥ���
1226 �����롣 */
1227
1228
1229 /***
1230 @seealso
1231 mplist_get () */
1232 M17NFunc
mplist_get_func(MPlist * plist,MSymbol key)1233 mplist_get_func (MPlist *plist, MSymbol key)
1234 {
1235 MPLIST_FIND (plist, key);
1236 return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_FUNC (plist));
1237 }
1238
1239 /*=*/
1240
1241 /***en
1242 @brief Add a property at the end of a property list.
1243
1244 The mplist_add () function appends at the end of property list
1245 $PLIST a property whose key is $KEY and value is $VAL. $KEY can
1246 be any symbol other than @c Mnil.
1247
1248 If $KEY is a managing key, $VAL must be a managed object. In this
1249 case, the reference count of $VAL is incremented by one.
1250
1251 @return
1252 If the operation was successful, mplist_add () returns a sublist of
1253 $PLIST whose first element is the just added one. Otherwise, it
1254 returns @c NULL. */
1255 /***ja
1256 @brief �ץ�ѥƥ��ꥹ�������˥ץ�ѥƥ����ɲä���.
1257
1258 �ؿ� mplist_add () �ϡ��ץ�ѥƥ��ꥹ�� $PLIST �������˥����� $KEY
1259 ���ͤ� $VAL �Ǥ���ץ�ѥƥ����ɲä��롣$KEY �ϡ�@c Mnil �ʳ���Ǥ�դΥ���ܥ�Ǥ褤��
1260
1261 $KEY �����������ʤ�С�$VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢
1262 $VAL �λ��ȿ��� 1 ���䤵��롣
1263
1264 @return
1265 ��������������� mplist_add () ���ɲä��줿���Ǥ���Ϥޤ� $PLIST
1266 ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */
1267
1268 MPlist *
mplist_add(MPlist * plist,MSymbol key,void * val)1269 mplist_add (MPlist *plist, MSymbol key, void *val)
1270 {
1271 if (key == Mnil)
1272 MERROR (MERROR_PLIST, NULL);
1273 MPLIST_FIND (plist, Mnil);
1274 if (val && key->managing_key)
1275 M17N_OBJECT_REF (val);
1276 MPLIST_KEY (plist) = key;
1277 MPLIST_VAL (plist) = val;
1278 MPLIST_NEW (plist->next);
1279 return plist;
1280 }
1281
1282 /*=*/
1283
1284 /***en
1285 @brief Add a property at the beginning of a property list.
1286
1287 The mplist_push () function inserts at the beginning of property
1288 list $PLIST a property whose key is $KEY and value is $VAL.
1289
1290 If $KEY is a managing key, $VAL must be a managed object. In this
1291 case, the reference count of $VAL is incremented by one.
1292
1293 @return
1294 If the operation was successful, this function returns $PLIST.
1295 Otherwise, it returns @c NULL. */
1296 /***ja
1297 @brief �ץ�ѥƥ��ꥹ�Ȥ���Ƭ�˥ץ�ѥƥ�����������.
1298
1299 �ؿ� mplist_push () �ϥץ�ѥƥ��ꥹ�� $PLIST ����Ƭ�˥����� $KEY
1300 ���ͤ� $VAL �Ǥ��륪�֥������Ȥ��������롣
1301
1302 $KEY �����������ʤ�С�$VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢
1303 $VAL �λ��ȿ��� 1 ���䤵��롣
1304
1305 @return
1306 ��������������Ф��δؿ��� $PLIST ���֤��������Ǥʤ����@c NULL
1307 ���֤��� */
1308
1309 MPlist *
mplist_push(MPlist * plist,MSymbol key,void * val)1310 mplist_push (MPlist *plist, MSymbol key, void *val)
1311 {
1312 MPlist *pl;
1313
1314 if (key == Mnil)
1315 MERROR (MERROR_PLIST, NULL);
1316 MPLIST_NEW (pl);
1317 MPLIST_KEY (pl) = MPLIST_KEY (plist);
1318 MPLIST_VAL (pl) = MPLIST_VAL (plist);
1319 if (MPLIST_NESTED_P (plist))
1320 MPLIST_SET_NESTED_P (pl);
1321 MPLIST_NEXT (pl) = MPLIST_NEXT (plist);
1322 plist->next = pl;
1323 if (val && key->managing_key)
1324 M17N_OBJECT_REF (val);
1325 MPLIST_KEY (plist) = key;
1326 MPLIST_VAL (plist) = val;
1327 return plist;
1328 }
1329
1330 /*=*/
1331
1332 /***en
1333 @brief Remove a property at the beginning of a property list.
1334
1335 The mplist_pop () function removes a property at the beginning of
1336 property list $PLIST. As a result, the second key and value of
1337 the $PLIST become the first ones.
1338
1339 @return
1340 If the operation was successful, this function return the value of
1341 the just popped property. Otherwise, it returns @c NULL. */
1342 /***ja
1343 @brief �ץ�ѥƥ��ꥹ�Ȥ���Ƭ����ץ�ѥƥ���������.
1344
1345 �ؿ� mplist_pop () �ϥץ�ѥƥ��ꥹ�� $PLIST ����Ƭ�Υץ�ѥƥ����
1346 �����롣��̤Ȥ��ơ�����2���ܤΥ������ͤ���Ƭ�Υ������ͤˤʤ롣
1347
1348 @return
1349 ��������������С����δؿ��Ϻ�����줿�ץ�ѥƥ����ͤ��֤��������Ǥʤ����
1350 @c NULL ���֤��� */
1351
1352 void *
mplist_pop(MPlist * plist)1353 mplist_pop (MPlist *plist)
1354 {
1355 void *val;
1356 MPlist *next;
1357
1358 if (MPLIST_TAIL_P (plist))
1359 return NULL;
1360 val = MPLIST_VAL (plist);
1361 next = MPLIST_NEXT (plist);
1362 MPLIST_KEY (plist) = MPLIST_KEY (next);
1363 MPLIST_VAL (plist) = MPLIST_VAL (next);
1364 if (MPLIST_KEY (plist) != Mnil
1365 && MPLIST_KEY (plist)->managing_key
1366 && MPLIST_VAL (plist))
1367 M17N_OBJECT_REF (MPLIST_VAL (plist));
1368 MPLIST_NEXT (plist) = MPLIST_NEXT (next);
1369 if (plist->next)
1370 M17N_OBJECT_REF (plist->next);
1371 M17N_OBJECT_UNREF (next);
1372 return val;
1373 }
1374
1375 /*=*/
1376 /***en
1377 @brief Find a property of a specific key in a property list.
1378
1379 The mplist_find_by_key () function searches property list
1380 $PLIST from the beginning for a property whose key is $KEY. If
1381 such a property is found, a sublist of $PLIST whose first element
1382 is the found one is returned. Otherwise, @c NULL is returned.
1383
1384 If $KEY is @c Mnil, it returns a sublist of $PLIST whose
1385 first element is the last one of $PLIST. */
1386 /***ja
1387 @brief �ץ�ѥƥ��ꥹ���椫�����Υ�������ĥץ�ѥƥ���õ��.
1388
1389 �ؿ� mplist_find_by_key () �ϥץ�ѥƥ��ꥹ�� $PLIST
1390 ��Ϥᤫ��õ ���ơ������� $KEY
1391 �Ǥ���ץ�ѥƥ��Ĥ��롣���Ĥ���С����Υץ�ѥƥ�����Ϥޤ�
1392 $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤���
1393
1394 $KEY �� @c Mnil �ʤ�С�$PLIST �κǸ�����Ǥ���Ϥޤ���ʬ�ꥹ�Ȥ��֤��� */
1395
1396 MPlist *
mplist_find_by_key(MPlist * plist,MSymbol key)1397 mplist_find_by_key (MPlist *plist, MSymbol key)
1398 {
1399 MPLIST_FIND (plist, key);
1400 return (MPLIST_TAIL_P (plist)
1401 ? (key == Mnil ? plist : NULL)
1402 : plist);
1403 }
1404
1405 /*=*/
1406 /***en
1407 @brief Find a property of a specific value in a property list.
1408
1409 The mplist_find_by_value () function searches property list $PLIST
1410 from the beginning for a property whose value is $VAL. If such a
1411 property is found, a sublist of $PLIST whose first element is the
1412 found one is returned. Otherwise, @c NULL is returned. */
1413 /***ja
1414 @brief �ץ�ѥƥ��ꥹ���椫�������ͤ���ĥץ�ѥƥ���õ��.
1415
1416 �ؿ� mplist_find_by_value () �ϥץ�ѥƥ��ꥹ�� $PLIST
1417 ��Ϥᤫ��õ���ơ��ͤ� $VAL
1418 �Ǥ���ץ�ѥƥ��Ĥ��롣���Ĥ���С����Υץ�ѥƥ�����Ϥޤ�
1419 $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */
1420
1421 MPlist *
mplist_find_by_value(MPlist * plist,void * val)1422 mplist_find_by_value (MPlist *plist, void *val)
1423 {
1424 MPLIST_DO (plist, plist)
1425 {
1426 if (MPLIST_VAL (plist) == val)
1427 return plist;
1428 }
1429 return NULL;
1430 }
1431
1432 /*=*/
1433
1434 /***en
1435 @brief Return the next sublist of a property list.
1436
1437 The mplist_next () function returns a pointer to the sublist of
1438 property list $PLIST, which begins at the second element in $PLIST. If the
1439 length of $PLIST is zero, it returns @c NULL. */
1440 /***ja
1441 @brief �ץ�ѥƥ��ꥹ�Ȥμ�����ʬ�ꥹ�Ȥ��֤�.
1442
1443 �ؿ� mplist_next () �ϥץ�ѥƥ��ꥹ�� $PLIST �� 2
1444 ���ܤ����Ǥ���Ϥޤ���ʬ�ꥹ�ȤؤΥݥ����֤���$PLIST ��Ĺ���� 0
1445 �ʤ�� @c NULL ���֤��� */
1446
1447 MPlist *
mplist_next(MPlist * plist)1448 mplist_next (MPlist *plist)
1449 {
1450 return (MPLIST_TAIL_P (plist) ? NULL : plist->next);
1451 }
1452
1453 /*=*/
1454
1455 /***en
1456 @brief Set the first property in a property list.
1457
1458 The mplist_set () function sets the key and the value of the first
1459 property in property list $PLIST to $KEY and $VALUE, respectively.
1460 See the documentation of mplist_add () for the restriction on $KEY
1461 and $VAL.
1462
1463 @return
1464 If the operation was successful, mplist_set () returns $PLIST.
1465 Otherwise, it returns @c NULL. */
1466 /***ja
1467 @brief �ץ�ѥƥ��ꥹ�Ȥκǽ�Υץ�ѥƥ������ꤹ��.
1468
1469 �ؿ� mplist_set () �ϥץ�ѥƥ��ꥹ�� $PLIST
1470 �κǽ�Υץ�ѥƥ��Υ������ͤ줾�� $KEY �� $VALUE �����ꤹ�롣
1471 $KEY �� $VAL ���Ф������¤ˤĤ��Ƥϡ�mplist_add () �������ȡ�
1472
1473 @return
1474 ��������������� mplist_set () �� $PLIST ���֤��������Ǥʤ���� @c NULL ���֤��� */
1475
1476 MPlist *
mplist_set(MPlist * plist,MSymbol key,void * val)1477 mplist_set (MPlist *plist, MSymbol key, void * val)
1478 {
1479 if (key == Mnil)
1480 {
1481 if (! MPLIST_TAIL_P (plist))
1482 {
1483 key = MPLIST_KEY (plist);
1484 M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
1485 MPLIST_KEY (plist) = Mnil;
1486 if (key->managing_key)
1487 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1488 plist->next = NULL;
1489 }
1490 }
1491 else
1492 {
1493 if (val && key->managing_key)
1494 M17N_OBJECT_REF (val);
1495 if (! MPLIST_TAIL_P (plist)
1496 && MPLIST_KEY (plist)->managing_key)
1497 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1498 MPLIST_SET (plist, key, val);
1499 }
1500 return plist;
1501 }
1502
1503 /*=*/
1504
1505 /***en
1506 @brief Return the length of a property list.
1507
1508 The mplist_length () function returns the number of properties in
1509 property list $PLIST. */
1510 /***ja
1511 @brief �ץ�ѥƥ��ꥹ�Ȥ�Ĺ�����֤�.
1512
1513 �ؿ� mplist_length () �ϥץ�ѥƥ��ꥹ�� $PLIST ��Υץ�ѥƥ��ο����֤��� */
1514
1515 int
mplist_length(MPlist * plist)1516 mplist_length (MPlist *plist)
1517 {
1518 int n;
1519
1520 for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next);
1521 return n;
1522 }
1523
1524 /*=*/
1525
1526 /***en
1527 @brief Return the key of the first property in a property list.
1528
1529 The mplist_key () function returns the key of the first property
1530 in property list $PLIST. If the length of $PLIST is zero,
1531 it returns @c Mnil. */
1532 /***ja
1533 @brief �ץ�ѥƥ��ꥹ����κǽ�Υץ�ѥƥ��Υ������֤�.
1534
1535 �ؿ� mplist_key () �ϡ��ץ�ѥƥ��ꥹ�� $PLIST
1536 ��κǽ�Υץ�ѥƥ��Υ������֤���$PLIST ��Ĺ���� 0 �ʤ�С� @c Mnil
1537 ���֤��� */
1538
1539 MSymbol
mplist_key(MPlist * plist)1540 mplist_key (MPlist *plist)
1541 {
1542 return MPLIST_KEY (plist);
1543 }
1544
1545 /*=*/
1546
1547 /***en
1548 @brief Return the value of the first property in a property list.
1549
1550 The mplist_value () function returns the value of the first
1551 property in property list $PLIST. If the length of $PLIST
1552 is zero, it returns @c NULL. */
1553 /***ja
1554 @brief �ץ�ѥƥ��ꥹ����κǽ�Υץ�ѥƥ����ͤ��֤�.
1555
1556 �ؿ� mplist_value () �ϡ��ץ�ѥƥ��ꥹ�� $PLIST ��κǽ�Υץ�ѥƥ����ͤ��֤���
1557 $PLIST ��Ĺ���� 0 �ʤ�С� @c Mnil ���֤��� */
1558
1559 void *
mplist_value(MPlist * plist)1560 mplist_value (MPlist *plist)
1561 {
1562 return MPLIST_VAL (plist);
1563 }
1564
1565 /***en
1566 @brief Generate a property list by deserializing an M-text.
1567
1568 The mplist_deserialize () function parses M-text $MT and returns a
1569 property list.
1570
1571 The syntax of $MT is as follows.
1572
1573 MT ::= '(' ELEMENT * ')'
1574
1575 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1576
1577 SYMBOL ::= ascii-character-sequence
1578
1579 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1580 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1581
1582 M-TEXT ::= '"' character-sequence '"'
1583
1584 Each alternatives of @c ELEMENT is assigned one of these keys: @c
1585 Msymbol, @c Minteger, @c Mtext, @c Mplist
1586
1587 In an ascii-character-sequence, a backslash (\) is used as the escape
1588 character, which means that, for instance, <tt>abc\ def</tt>
1589 produces a symbol whose name is of length seven with the fourth
1590 character being a space. */
1591 /***ja
1592 @brief M-text ��ǥ��ꥢ�饤�����ƥץ�ѥƥ��ꥹ�Ȥ���.
1593
1594 �ؿ� mplist_deserialize () �� M-text $MT ����Ϥ��ƥץ�ѥƥ��ꥹ�Ȥ��֤���
1595
1596 $MT �Υ��å����ϰʲ����̤ꡣ
1597
1598 MT ::= '(' ELEMENT * ')'
1599
1600 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1601
1602 SYMBOL ::= ��������ʸ����
1603
1604 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1605 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1606
1607 M-TEXT ::= '"' character-sequence '"'
1608
1609 @c ELEMENT �γ������ϥ�����@c Msymbol, @c Minteger, @c Mtext,
1610 @c Mplist �Τ����줫�������Ƥ��Ƥ��롣
1611
1612 ��������ʸ������Ǥϡ��Хå�����å��� (\) ������������ʸ���Ȥ����Ѥ����롣���Ȥ���
1613 <tt>abc\ def</tt> �� 4 ʸ���ܤ�����ʸ���Ǥ���Ĺ���� 7
1614 �Ǥ������̾������ĥ���ܥ���������롣 */
1615
1616 MPlist *
mplist_deserialize(MText * mt)1617 mplist_deserialize (MText *mt)
1618 {
1619 MPlist *plist;
1620 MText *tmp = NULL;
1621
1622 if (mt->format > MTEXT_FORMAT_UTF_8)
1623 {
1624 if (MTEXT_READ_ONLY_P (mt))
1625 mt = tmp = mtext_cpy (mtext (), mt);
1626 else
1627 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1628 }
1629 plist = mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
1630 if (tmp)
1631 M17N_OBJECT_UNREF (tmp);
1632 return plist;
1633 }
1634
1635 /*** @} */
1636
1637 /*** @addtogroup m17nDebug */
1638 /*=*/
1639 /*** @{ */
1640
1641 /***en
1642 @brief Dump a property list.
1643
1644 The mdebug_dump_plist () function prints a property list $PLIST in
1645 a human readable way to the stderr or to what specified by the
1646 environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how
1647 many columns to indent the lines but the first one.
1648
1649 @return
1650 This function returns $PLIST. */
1651 /***ja
1652 @brief �ץ�ѥƥ��ꥹ�Ȥ����פ���.
1653
1654 �ؿ� mdebug_dump_plist () �ϥץ�ѥƥ��ꥹ�� $PLIST ��ɸ�२�顼��
1655 �Ϥ⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲�
1656 �ɤʷ��ǰ������롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣
1657
1658 @return
1659 ���δؿ��� $PLIST ���֤��� */
1660 MPlist *
mdebug_dump_plist(MPlist * plist,int indent)1661 mdebug_dump_plist (MPlist *plist, int indent)
1662 {
1663 char *prefix = (char *) alloca (indent + 1);
1664 MPlist *pl;
1665
1666 memset (prefix, 32, indent);
1667 prefix[indent] = 0;
1668
1669 fprintf (mdebug__output, "(");
1670 MPLIST_DO (pl, plist)
1671 {
1672 if (pl != plist)
1673 fprintf (mdebug__output, "\n%s ", prefix);
1674 write_element (NULL, pl, indent + 1);
1675 }
1676 fprintf (mdebug__output, ")");
1677 return plist;
1678 }
1679
1680 /*** @} */
1681
1682 /*
1683 Local Variables:
1684 coding: euc-japan
1685 End:
1686 */
1687