1 /* plist.c -- plist module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
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.
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.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 @brief Property List objects and API for them.
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
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
39 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
41 @e ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È (¤Þ¤¿¤Ï @e plist) ¤Ï 0 ¸Ä°Ê¾å¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥ê
42 ¥¹¥È¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¤Ï @e ¥¡¼ ¤È @e ÃÍ ¤«¤é¤Ê¤ë¡£¥¡¼¤Ï¥·¥ó¥Ü¥ë
43 ¤Ç¤¢¤ê¡¢ÃÍ¤Ï <tt>(void *)</tt> ¤Ë¥¥ã¥¹¥È¤Ç¤¤ë¤â¤Î¤Ê¤é¤Ð²¿¤Ç¤âÎÉ
46 ¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤¬ @e ´ÉÍý¥¡¼ ¤Ê¤é¤Ð¡¢¤½¤Î @e ÃÍ ¤Ï@e ´ÉÍý²¼
47 ¥ª¥Ö¥¸¥§¥¯¥È ¤Ç¤¢¤ë¡£¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¼«ÂΤâ´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include "m17n-misc.h"
62 #include "character.h"
67 static M17NObjectArray plist_table;
69 /** Set PLIST to a newly allocated plist object. */
71 #define MPLIST_NEW(plist) \
73 M17N_OBJECT (plist, free_plist, MERROR_PLIST); \
74 M17N_OBJECT_REGISTER (plist_table, plist); \
78 /** Set the element of PLIST to KEY and VAL. If PLIST is an anchor,
79 append a new anchor. */
81 #define MPLIST_SET(plist, key, val) \
83 MPLIST_KEY (plist) = (key); \
84 MPLIST_VAL (plist) = (val); \
85 if (! (plist)->next) \
86 MPLIST_NEW ((plist)->next); \
90 /** Set the element of PLIST to KEY and VAL. PLIST must be an anchor.
91 Append a new anchor and set PLIST to that anchor. */
93 #define MPLIST_SET_ADVANCE(plist, key, val) \
95 MPLIST_KEY (plist) = (key); \
96 MPLIST_VAL (plist) = (val); \
97 MPLIST_NEW ((plist)->next); \
98 plist = (plist)->next; \
103 free_plist (void *object)
105 MPlist *plist = (MPlist *) object;
108 MPlist *next = plist->next;
110 if (MPLIST_KEY (plist) != Mnil && MPLIST_KEY (plist)->managing_key)
111 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
112 M17N_OBJECT_UNREGISTER (plist_table, plist);
115 } while (plist && plist->control.ref_count == 1);
116 M17N_OBJECT_UNREF (plist);
121 /* Load a plist from a string. */
123 #define READ_CHUNK 0x10000
127 /* File pointer if the stream is associated with a file. Otherwise
131 unsigned char buffer[READ_CHUNK];
132 unsigned char *p, *pend;
136 get_byte (MStream *st)
140 if (! st->fp || st->eof)
142 n = fread (st->buffer, 1, READ_CHUNK, st->fp);
148 st->p = st->buffer + 1;
149 st->pend = st->buffer + n;
150 return st->buffer[0];
154 ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
157 #define UNGETC(c, st) \
160 /** Mapping table for reading a number. Hexadecimal chars
161 (0..9,A..F,a..F) are mapped to the corresponding numbers.
162 Apostrophe (code 39) is mapped to 254. All the other bytes are
164 unsigned char hex_mnemonic[256];
166 /** Mapping table for escaped characters. Mnemonic characters (e, b,
167 f, n, r, or t) that follows '\' are mapped to the corresponding
168 character code. All the other bytes are mapped to themselves. */
169 unsigned char escape_mnemonic[256];
172 /** Read an integer from the stream ST. It is assumed that we have
173 already read one character C. */
176 read_decimal (MStream *st, int c)
180 while (c >= '0' && c <= '9')
182 num = (num * 10) + (c - '0');
191 /** Read an unsigned from the stream ST. */
194 read_hexadesimal (MStream *st)
199 while ((c = GETC (st)) != EOF
200 && (n = hex_mnemonic[c]) < 16)
201 num = (num << 4) | n;
208 /** Read an M-text element from ST, and add it to LIST. Return a list
209 for the next element. */
212 read_mtext_element (MPlist *plist, MStream *st)
214 unsigned char buffer[1024];
216 unsigned char *buf = buffer;
220 while ((c = GETC (st)) != EOF && c != '"')
222 if (i + MAX_UTF8_CHAR_BYTES >= bufsize)
227 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
228 memcpy (buf, buffer, i);
231 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
243 c = read_hexadesimal (st);
249 c = escape_mnemonic[c];
255 MPLIST_SET_ADVANCE (plist, Mtext,
256 mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
263 read_character (MStream *st, int c)
265 unsigned char buf[MAX_UTF8_CHAR_BYTES + 1];
266 int len = CHAR_BYTES_BY_HEAD (c);
270 for (i = 1; i < len; i++)
274 || (c & 0xC0) != 0x80)
279 c = STRING_CHAR_UTF8 (buf);
286 /** Read an integer element from ST, and add it to LIST. Return a
287 list for the next element. It is assumed that we have already
288 read the character C. */
291 read_integer_element (MPlist *plist, MStream *st, int c)
295 if (c == '0' || c == '#')
299 num = read_hexadesimal (st);
301 num = read_decimal (st, c);
310 if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
313 num = read_character (st, c);
320 else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c))
321 num = escape_mnemonic[c];
323 num = read_character (st, c);
327 num = - read_decimal (st, GETC (st));
329 num = read_decimal (st, c);
331 MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
335 /** Read a symbol element from ST, and add it to LIST. Return a list
336 for the next element. */
339 read_symbol_element (MPlist *plist, MStream *st)
341 unsigned char buffer[1024];
343 unsigned char *buf = buffer;
347 while ((c = GETC (st)) != EOF
349 && c != ')' && c != '(' && c != '"')
356 MTABLE_MALLOC (buf, bufsize, MERROR_PLIST);
357 memcpy (buf, buffer, i);
360 MTABLE_REALLOC (buf, bufsize, MERROR_PLIST);
367 c = escape_mnemonic[c];
373 MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
381 /* Read an element of various type from stream ST, and add it to LIST.
382 Return a list for the next element. The element type is decided by
383 the first token character found as below:
386 '0'..'9', '-': integer
387 '?': integer representing character code
388 the other ASCII letters: symbol
392 read_element (MPlist *plist, MStream *st)
396 /* Skip separators and comments. */
399 while ((c = GETC (st)) != EOF && c <= ' ');
402 while ((c = GETC (st)) != EOF && c != '\n');
413 while ((p = read_element (p, st)));
414 MPLIST_SET_ADVANCE (plist, Mplist, pl);
418 return read_mtext_element (plist, st);
419 if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
420 return read_integer_element (plist, st, c);
421 if (c == EOF || c == ')')
424 return read_symbol_element (plist, st);
428 write_element (MText *mt, MPlist *plist)
430 if (MPLIST_SYMBOL_P (plist))
432 MSymbol sym = MPLIST_SYMBOL (plist);
436 MTEXT_CAT_ASCII (mt, "nil");
440 char *name = MSYMBOL_NAME (sym);
441 char *buf = alloca (MSYMBOL_NAMELEN (sym) * 2 + 1), *p = buf;
445 if (*name <= ' ' || *name == '"' || *name == ')' || *name == ')')
450 MTEXT_CAT_ASCII (mt, buf);
453 else if (MPLIST_INTEGER_P (plist))
455 int num = MPLIST_INTEGER (plist);
458 sprintf (buf, "%d", num);
459 MTEXT_CAT_ASCII (mt, buf);
461 else if (MPLIST_PLIST_P (plist))
465 plist = MPLIST_PLIST (plist);
466 mtext_cat_char (mt, '(');
467 MPLIST_DO (pl, plist)
470 mtext_cat_char (mt, ' ');
471 write_element (mt, pl);
473 mtext_cat_char (mt, ')');
475 else if (MPLIST_MTEXT_P (plist))
477 mtext_cat_char (mt, '"');
478 /* Not yet implemnted */
479 mtext_cat_char (mt, '"');
483 /* Support functions for mdebug_dump_plist. */
486 dump_string (char *str)
488 char *p = str, *pend = p + strlen (p), *new, *p1;
490 new = p1 = alloca ((pend - p) * 4 + 1);
495 sprintf (p1, "\\x%02X", (unsigned char) *p);
513 fprintf (stderr, "%s", new);
517 dump_plist_element (MPlist *plist, int indent)
519 char *prefix = (char *) alloca (indent + 1);
522 memset (prefix, 32, indent);
525 key = MPLIST_KEY (plist);
526 fprintf (stderr, "(%s(#%d) ", msymbol_name (MPLIST_KEY (plist)),
527 plist->control.ref_count);
529 dump_string (msymbol_name (MPLIST_SYMBOL (plist)));
530 else if (key == Mtext)
531 mdebug_dump_mtext (MPLIST_MTEXT (plist), indent, 0);
532 else if (key == Minteger)
533 fprintf (stderr, "%x", MPLIST_INTEGER (plist));
534 else if (key == Mstring)
535 fprintf (stderr, "\"%s\"", MPLIST_STRING (plist));
536 else if (key == Mplist)
538 fprintf (stderr, "\n%s", prefix);
539 mdebug_dump_plist (MPLIST_PLIST (plist), indent);
542 fprintf (stderr, "0x%X", (unsigned) MPLIST_VAL (plist));
543 fprintf (stderr, ")");
553 plist_table.count = 0;
555 Minteger = msymbol ("integer");
556 Mplist = msymbol_as_managing_key ("plist");
557 Mtext = msymbol_as_managing_key ("mtext");
559 for (i = 0; i < 256; i++)
560 hex_mnemonic[i] = 255;
561 for (i = '0'; i <= '9'; i++)
562 hex_mnemonic[i] = i - '0';
563 for (i = 'A'; i <= 'F'; i++)
564 hex_mnemonic[i] = i - 'A' + 10;
565 for (i = 'a'; i <= 'f'; i++)
566 hex_mnemonic[i] = i - 'a' + 10;
567 for (i = 0; i < 256; i++)
568 escape_mnemonic[i] = i;
569 escape_mnemonic['e'] = 27;
570 escape_mnemonic['b'] = '\b';
571 escape_mnemonic['f'] = '\f';
572 escape_mnemonic['n'] = '\n';
573 escape_mnemonic['r'] = '\r';
574 escape_mnemonic['t'] = '\t';
575 escape_mnemonic['\\'] = '\\';
583 mdebug__report_object ("Plist", &plist_table);
587 /* Parse this form of PLIST:
588 (symbol:KEY1 TYPE1:VAL1 symbol:KEY2 TYPE2:VAL2 ...)
589 and return a newly created plist of this form:
590 (KEY1:VAL1 KEY2:VAL2 ...) */
593 mplist__from_plist (MPlist *plist)
599 while (! MPLIST_TAIL_P (plist))
603 if (! MPLIST_SYMBOL_P (plist))
604 MERROR (MERROR_PLIST, NULL);
605 key = MPLIST_SYMBOL (plist);
606 plist = MPLIST_NEXT (plist);
607 type = MPLIST_KEY (plist);
608 if (type->managing_key)
609 M17N_OBJECT_REF (MPLIST_VAL (plist));
610 MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
611 plist = MPLIST_NEXT (plist);
616 /** Parse this form of PLIST:
617 ((symbol:KEY1 ANY:VAL1 ... ) (symbol:KEY2 ANY:VAL2 ...) ...)
618 and return a newly created plist of this form:
619 (KEY1:(ANY:VAL1 ...) KEY2:(ANY:VAL2 ...) ...)
620 ANY can be any type. */
623 mplist__from_alist (MPlist *plist)
629 MPLIST_DO (plist, plist)
633 if (! MPLIST_PLIST_P (plist))
634 MERROR (MERROR_PLIST, NULL);
635 elt = MPLIST_PLIST (plist);
636 if (! MPLIST_SYMBOL_P (elt))
637 MERROR (MERROR_PLIST, NULL);
638 MPLIST_SET_ADVANCE (p, MPLIST_SYMBOL (elt), MPLIST_NEXT (elt));
639 M17N_OBJECT_REF (MPLIST_NEXT (elt));
646 mplist__from_file (FILE *fp)
653 st.p = st.pend = st.buffer;
656 while ((pl = read_element (pl, &st)));
661 /** Parse $STR of $N bytes and return a property list object. $FORMAT
662 must be either @c MTEXT_FORMAT_US_ASCII or @c MTEXT_FORMAT_UTF_8,
663 and controls how to produce @c STRING or @c M-TEXT in the
664 following definition.
666 The syntax of $STR is as follows.
668 PLIST ::= '(' ELEMENT * ')'
670 ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST
672 SYMBOL ::= ascii-character-sequence
674 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
676 UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
678 M-TEXT ::= '"' byte-sequence '"'
680 Each kind of @c ELEMENT is assigned one of these keys:
681 @c Msymbol, @c Mint, @c Munsigned, @c Mtext, @c Mplist
683 In an ascii-character-sequence, a backslush (\) is used as the escape
684 character, which means that, for instance, <tt>"abc\ def"</tt>
685 produces a symbol whose name is of length seven with the fourth
686 character being a space.
688 In a byte-sequence, "\r", "\n", "\e", and "\t" are replaced by CR,
689 NL, ESC, and TAB character respectively, "\xXX" are replaced by
690 byte 0xXX. After this replacement, the byte-sequence is decoded
691 into M-TEXT by $CODING. */
694 mplist__from_string (unsigned char *str, int n)
705 while ((pl = read_element (pl, &st)));
710 mplist__serialize (MText *mt, MPlist *plist)
714 MPLIST_DO (pl, plist)
717 mtext_cat_char (mt, ' ');
718 write_element (mt, pl);
724 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
729 /*** @addtogroup m17nPlist */
734 @brief Symbol whose name is "integer".
736 The symbol @c Minteger has the name <tt>"integer"</tt>. A value
737 of a property whose key is @c Minteger must be an integer. */
739 @brief "integer" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
741 ¥·¥ó¥Ü¥ë @c Minteger ¤Ï <tt>"integer"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¥¡¼¤¬
742 @c Minteger ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÀ°¿ôÃͤǤʤ¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ */
748 @brief Symbol whose name is "plist".
750 The symbol @c Mplist has the name <tt>"plist"</tt>. It is a
751 managing key. A value of a property whose key is @c Mplist must
754 @brief "plist" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
756 ¥·¥ó¥Ü¥ë @c Mplist ¤Ï <tt>"plist"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´É
757 Íý¥¡¼¤Ç¤¢¤ë¡£¥¡¼¤¬ @c Mplist ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃÍ¤Ï plist ¤Ç¤Ê¤¯
764 @brief Symbol whose name is "mtext".
766 The symbol @c Mtext has the name <tt>"mtext"</tt>. It is a
767 managing key. A value of a property whose key is @c Mtext must be an
771 @brief "mtext" ¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë.
773 ¥·¥ó¥Ü¥ë @c Mtext ¤Ï <tt>"mtext"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä´ÉÍý¥¡¼¤Ç¤¢
774 ¤ë¡£¥¡¼¤¬ @c Mtext ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ÎÃÍ¤Ï M-text ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê
781 @brief Create a property list object.
783 The mplist () function returns a newly created property list
784 object of length zero.
787 This function returns a newly created property list.
790 This function never fails. */
792 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë.
794 ´Ø¿ô mplist () ¤ÏŤµ 0 ¤Î¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯
798 ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£
801 ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£ */
814 @brief Copy a property list.
816 The mplist_copy () function copies property list $PLIST. In the
817 copy, the values are the same as those of $PLIST.
820 This function returns a newly created plist which is a copy of
824 This function never fails. */
826 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥³¥Ô¡¼¤¹¤ë.
828 ´Ø¿ô mplist_copy () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò¥³¥Ô¡¼¤¹¤ë¡£¥³¥Ô¡¼¤Î¤¹¤Ù¤Æ¤Î
829 Ãͤϥ³¥Ô¡¼¸µ $PLIST ¤ÎÃͤÈƱ¤¸¤Ç¤¢¤ë¡£
832 ¤³¤Î´Ø¿ô¤Ï¿·¤·¤¯ºî¤é¤ì¤¿¡¢$PLIST ¤Î¥³¥Ô¡¼¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òÊÖ¤¹¡£
835 ¤³¤Î´Ø¿ô¤Ï·è¤·¤Æ¼ºÇÔ¤·¤Ê¤¤¡£ */
838 mplist_copy (MPlist *plist)
840 MPlist *copy = mplist (), *pl = copy;
842 MPLIST_DO (plist, plist)
843 pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist));
850 @brief Set the value of a property in a property list.
852 The mplist_put () function searches property list $PLIST
853 from the beginning for a property whose key is $KEY. If such a
854 property is found, its value is changed to $VALUE. Otherwise, a
855 new property whose key is $KEY and value is $VALUE is appended at
856 the end of $PLIST. See the documentation of mplist_add () for
857 the restriction on $KEY and $VAL.
859 If $KEY is a managing key, $VAL must be a managed object. In this
860 case, the reference count of the old value, if not @c NULL, is
861 decremented by one, and that of $VAL is incremented by one.
864 If the operation was successful, mplist_put () returns a sublist of
865 $PLIST whose first element is the just modified or added one.
866 Otherwise, it returns @c NULL. */
868 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÀßÄꤹ¤ë.
870 ´Ø¿ô mplist_put () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢¥¡¼
871 ¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤò $VALUE ¤Ë
872 Êѹ¹¤¹¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¥¡¼¤¬ $KEY ¤ÇÃͤ¬ $VALUE ¤Ç¤¢¤ë¿·¤·¤¤
873 ¥×¥í¥Ñ¥Æ¥£¤¬$PLIST ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹¤ëÀ©¸Â¤Ë
874 ¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
876 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
877 ¤³¤Î¾ì¹ç¡¢¸Å¤¤Ãͤλ²¾È¿ô¤Ï @c NULL ¤Ç¤Ê¤±¤ì¤Ð 1 ¸º¤é¤µ¤ì¡¢$VAL ¤Î
878 »²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
881 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_put () ¤ÏÊѹ¹¤µ¤ì¤¿¤«Äɲ䵤줿Í×ÁǤ«¤é»Ï
882 ¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
885 mplist_put (MPlist *plist, MSymbol key, void *val)
888 MERROR (MERROR_PLIST, NULL);
889 MPLIST_FIND (plist, key);
890 if (key->managing_key)
892 if (! MPLIST_TAIL_P (plist))
893 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
894 M17N_OBJECT_REF (val);
896 MPLIST_SET (plist, key, val);
903 @brief Get the value of a property in a property list.
905 The mplist_get () function searches property list $PLIST
906 from the beginning for a property whose key is $KEY. If such a
907 property is found, a pointer to its value is returned as the type
908 of <tt>(void *)</tt>. If not found, @c NULL is returned.
910 When @c NULL is returned, there are two possibilities: one is the
911 case where no property is found (see above); the other is the case
912 where a property is found and its value is @c NULL. In case that
913 these two cases must be distinguished, use the mplist_find_by_key ()
916 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
918 ´Ø¿ô mplist_get () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ¤·¤Æ¡¢
919 ¥¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤ÎÃͤؤΥݥ¤
920 ¥ó¥¿¤ò <tt>(void *)</tt> ·¿¤ÇÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£
922 @c NULL ¤¬Ê֤俺ݤˤÏÆó¤Ä¤Î²ÄǽÀ¤¬¤¢¤ë:¾åµ¤Î¤è¤¦¤Ë¥×¥í¥Ñ¥Æ¥£¤¬
923 ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤È¡¢¥×¥í¥Ñ¥Æ¥£¤¬¸«¤Ä¤«¤ê¡¢¤½¤ÎÃͤ¬ @c NULL ¤Ç
924 ¤¢¤ë¾ì¹ç¤Ç¤¢¤ë¡£¤³¤ì¤é¤ò¶èÊ̤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ë¤Ï´Ø¿ô
925 mplist_find_by_key () ¤ò»È¤¦¤³¤È¡£ */
929 mplist_find_by_key () */
932 mplist_get (MPlist *plist, MSymbol key)
934 MPLIST_FIND (plist, key);
935 return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist));
941 @brief Add a property at the end of a property list.
943 The mplist_add () function appends at the end of property list
944 $PLIST a property whose key is $KEY and value is $VAL. $KEY can
945 be any symbol other than @c Mnil.
947 If $KEY is a managing key, $VAL must be a managed object. In this
948 case, the reference count of $VAL is incremented by one.
951 If the operation was successful, mplist_add () returns a sublist of
952 $PLIST whose first element is the just added one. Otherwise, it
955 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈËöÈø¤Ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤ë.
957 ´Ø¿ô mplist_add () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎËöÈø¤Ë¥¡¼¤¬ $KEY
958 ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤òÄɲ乤롣$KEY ¤Ï¡¢@c Mnil °Ê³°¤ÎǤ
961 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
962 ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
965 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mplist_add () ¤ÏÄɲ䵤줿Í×ÁǤ«¤é»Ï¤Þ¤ë $PLIST
966 ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
969 mplist_add (MPlist *plist, MSymbol key, void *val)
972 MERROR (MERROR_PLIST, NULL);
973 MPLIST_FIND (plist, Mnil);
974 if (key->managing_key)
975 M17N_OBJECT_REF (val);
976 MPLIST_KEY (plist) = key;
977 MPLIST_VAL (plist) = val;
978 MPLIST_NEW (plist->next);
985 @brief Push a property to a property list.
987 The mplist_push () function pushes at the top of property list
988 $PLIST a property whose key is $KEY and value is $VAL.
990 If $KEY is a managing key, $VAL must be a managed object. In this
991 case, the reference count of $VAL is incremented by one.
994 If the operation was successful, this function returns $PLIST.
995 Otherwise, it returns @c NULL. */
997 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥×¥Ã¥·¥å¤¹¤ë.
999 ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î¾å¤Ë¤Ë¥¡¼¤¬ $KEY
1000 ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¥×¥Ã¥·¥å¤¹¤ë¡£
1002 $KEY ¤¬´ÉÍý¥¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1003 ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
1006 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL ¤ò
1010 mplist_push (MPlist *plist, MSymbol key, void *val)
1015 MERROR (MERROR_PLIST, NULL);
1017 MPLIST_KEY (pl) = MPLIST_KEY (plist);
1018 MPLIST_VAL (pl) = MPLIST_VAL (plist);
1019 pl->next = plist->next;
1021 if (key->managing_key)
1022 M17N_OBJECT_REF (val);
1023 MPLIST_KEY (plist) = key;
1024 MPLIST_VAL (plist) = val;
1031 @brief Pop a property from a property list.
1033 The mplist_pop () function pops the topmost property from property
1034 list $PLIST. As a result, the key and value of $PLIST becomes
1035 those of the next of $PLIST.
1038 If the operation was successful, this function return the value of
1039 the just popped property. Otherwise, it returns @c NULL. */
1041 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ý¥Ã¥×¤¹¤ë.
1043 ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤«¤éºÇ¾å°Ì¤Î¥×¥í¥Ñ¥Æ¥£
1044 ¤ò¥Ý¥Ã¥×¤¹¤ë¡£·ë²Ì¤È¤·¤Æ $PLIST ¤Î¥¡¼¤ÈÃÍ¤Ï $PLIST ¤Î¼¡¤Î¥¡¼¤ÈÃÍ
1048 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Ý¥Ã¥×¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
1049 ¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£ */
1052 mplist_pop (MPlist *plist)
1057 if (MPLIST_TAIL_P (plist))
1059 val = MPLIST_VAL (plist);
1061 MPLIST_KEY (plist) = MPLIST_KEY (next);
1062 MPLIST_VAL (plist) = MPLIST_VAL (next);
1063 if (MPLIST_KEY (plist) != Mnil
1064 && MPLIST_KEY (plist)->managing_key
1065 && MPLIST_VAL (plist))
1066 M17N_OBJECT_REF (MPLIST_VAL (plist));
1067 plist->next = next->next;
1069 M17N_OBJECT_REF (plist->next);
1070 M17N_OBJECT_UNREF (next);
1076 @brief Find a property of a specific key in a property list.
1078 The mplist_find_by_key () function searches property list
1079 $PLIST from the beginning for a property whose key is $KEY. If
1080 such a property is found, a sublist of $PLIST whose first element
1081 is the found one is returned. Otherwise, @c NULL is returned.
1083 If $KEY is @c Mnil, it returns a sublist of $PLIST whose
1084 first element is the last one of $PLIST. */
1086 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥¡¼¤ò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
1088 ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ
1089 ¤·¤Æ¡¢¥¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1090 ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL
1093 $KEY ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢$PLIST ¤ÎºÇ¸å¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤ò
1097 mplist_find_by_key (MPlist *plist, MSymbol key)
1099 MPLIST_FIND (plist, key);
1100 return (MPLIST_TAIL_P (plist)
1101 ? (key == Mnil ? plist : NULL)
1107 @brief Find a property of a specific value in a property list.
1109 The mplist_find_by_value () function searches property list $PLIST
1110 from the beginning for a property whose value is $VAL. If such a
1111 property is found, a sublist of $PLIST whose first element is the
1112 found one is returned. Otherwise, @c NULL is returned. */
1114 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
1116 ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤é
1117 õ¤·¤Æ¡¢Ãͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
1118 ¥Ñ¥Æ¥£¤«¤é»Ï¤Þ¤ë $PLIST ¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð@c NULL
1122 mplist_find_by_value (MPlist *plist, void *val)
1124 MPLIST_DO (plist, plist)
1126 if (MPLIST_VAL (plist) == val)
1135 @brief Return the next sublist of a property list.
1137 The mplist_next () function returns a pointer to the sublist of
1138 property list $PLIST, which begins at the second element in $PLIST. If the
1139 length of $PLIST is zero, it returns @c NULL. */
1141 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¼¡¤ÎÉôʬ¥ê¥¹¥È¤òÊÖ¤¹.
1143 ´Ø¿ô mplist_next () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î£²ÈÖÌÜ
1144 ¤ÎÍ×ÁǤ«¤é»Ï¤Þ¤ëÉôʬ¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê
1145 ¤é¤Ð @c NULL ¤òÊÖ¤¹¡£ */
1148 mplist_next (MPlist *plist)
1150 return (MPLIST_TAIL_P (plist) ? NULL : plist->next);
1156 @brief Set the first property in a property list.
1158 The mplist_set () function sets the key and value of the first
1159 property in property list $PLIST to $KEY and $VALUE, respectively.
1160 See the documentation of mplist_add () for the restriction on $KEY
1164 If the operation was successful, mplist_set () returns $PLIST.
1165 Otherwise, it returns @c NULL. */
1167 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë.
1169 ´Ø¿ô mplist_set () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î
1170 ¥¡¼¤ÈÃͤò¤½¤ì¤¾¤ì $KEY ¤È $VALUE ¤ËÀßÄꤹ¤ë¡£$KEY ¤È $VAL ¤ËÂФ¹
1171 ¤ëÀ©¸Â¤Ë¤Ä¤¤¤Æ¤Ï¡¢mplist_add () ¤ÎÀâÌÀ¤ò»²¾È¡£
1174 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mplist_set () ¤Ï $PLIST ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
1178 mplist_set (MPlist *plist, MSymbol key, void * val)
1182 if (! MPLIST_TAIL_P (plist))
1184 key = MPLIST_KEY (plist);
1185 M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
1186 MPLIST_KEY (plist) = Mnil;
1187 if (key->managing_key && MPLIST_VAL (plist))
1188 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1194 if (! MPLIST_TAIL_P (plist)
1195 && MPLIST_KEY (plist)->managing_key
1196 && MPLIST_VAL (plist))
1197 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
1198 if (key->managing_key)
1199 M17N_OBJECT_REF (val);
1200 MPLIST_SET (plist, key, val);
1208 @brief Return the length of a property list.
1210 The mplist_length () function returns the number of properties in
1211 property list $PLIST. */
1213 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎŤµ¤òÊÖ¤¹.
1215 ´Ø¿ô mplist_length () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î¥×¥í¥Ñ¥Æ¥£¤Î¿ô
1219 mplist_length (MPlist *plist)
1223 for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next);
1230 @brief Return the key of the first property in a property list.
1232 The mplist_key () function returns the key of the first property
1233 in property list $PLIST. If the length of $PLIST is zero,
1234 it returns @c Mnil. */
1236 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤òÊÖ¤¹.
1238 ´Ø¿ô mplist_key () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤ÎºÇ
1239 ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤òÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1243 mplist_key (MPlist *plist)
1245 return MPLIST_KEY (plist);
1251 @brief Return the value of the first property in a property list.
1253 The mplist_value () function returns the value of the first
1254 property in property list $PLIST. If the length of $PLIST
1255 is zero, it returns @c NULL. */
1257 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤òÊÖ¤¹.
1259 ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î
1260 ºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò
1264 mplist_value (MPlist *plist)
1266 return MPLIST_VAL (plist);
1270 @brief Generate a property list by deserializaing an M-text.
1272 The mplist_deserialize () function parses M-text $MT and returns a
1275 The syntax of $MT is as follows.
1277 MT ::= '(' ELEMENT * ')'
1279 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1281 SYMBOL ::= ascii-character-sequence
1283 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1284 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1286 M-TEXT ::= '"' character-sequence '"'
1288 Each alternatives of @c ELEMENT is assigned one of these keys: @c
1289 Msymbol, @c Minteger, @c Mtext, @c Mplist
1291 In an ascii-character-sequence, a backslush (\) is used as the escape
1292 character, which means that, for instance, <tt>"abc\ def"</tt>
1293 produces a symbol whose name is of length seven with the fourth
1294 character being a space. */
1296 @brief M-text ¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤òºî¤ë.
1298 ´Ø¿ô mplist_deserialize () ¤Ï M-text $MT ¤ò²òÀϤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹
1301 $MT ¤Î¥·¥ó¥¿¥Ã¥¯¥¹¤Ï°Ê²¼¤ÎÄ̤ꡣ
1303 MT ::= '(' ELEMENT * ')'
1305 ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST
1307 SYMBOL ::= ¥¢¥¹¥¡¼Ê¸»úÎó
1309 INTEGER ::= '-' ? [ '0' | .. | '9' ]+
1310 | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+
1312 M-TEXT ::= '"' character-sequence '"'
1314 @c ELEMENT ¤Î³ÆÁªÂò»è¤Ï¥¡¼¡§@c Msymbol, @c Minteger, @c Mtext,
1315 @c Mplist ¤Î¤¤¤º¤ì¤«¤ò³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¡£
1317 ¥¢¥¹¥¡¼Ê¸»úÎóÆâ¤Ç¤Ï¡¢¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å (\) ¤¬¥¨¥¹¥±¡¼¥×ʸ»ú¤È¤·¤Æ
1318 ÍѤ¤¤é¤ì¤ë¡£¤¿¤È¤¨¤Ð <tt>"abc\ def"</tt> ¤Ï£´Ê¸»úÌܤ¬¶õÇòʸ»ú¤Ç¤¢
1319 ¤êŤµ¤¬£·¤Ç¤¢¤ë»ý¤Ä̾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë¤òÀ¸À®¤¹¤ë¡£ */
1322 mplist_deserialize (MText *mt)
1324 if (mt->format > MTEXT_FORMAT_UTF_8)
1326 if (mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8) < 0)
1327 MERROR (MERROR_PLIST, NULL);
1329 return mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt));
1334 /*** @addtogroup m17nDebug */
1339 @brief Dump a property list.
1341 The mdebug_dump_plist () function prints a property list $PLIST in
1342 a human readable way to the stderr. $INDENT specifies how many
1343 columns to indent the lines but the first one.
1346 This function returns $PLIST. */
1348 @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò¥À¥ó¥×¤¹¤ë.
1350 ´Ø¿ô mdebug_dump_plist () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò stderr ¤Ë¿Í
1351 ´Ö¤Ë²ÄÆÉ¤Ê ·Á¤Ç°õºþ¤¹¤ë¡£ $UNDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ
1355 ¤³¤Î´Ø¿ô¤Ï $PLIST ¤òÊÖ¤¹¡£ */
1357 mdebug_dump_plist (MPlist *plist, int indent)
1359 char *prefix = (char *) alloca (indent + 1);
1363 memset (prefix, 32, indent);
1366 fprintf (stderr, "(");
1367 MPLIST_DO (pl, plist)
1372 fprintf (stderr, "\n%s ", prefix);
1373 dump_plist_element (pl, indent + 2);
1375 fprintf (stderr, ")");