*** empty log message ***
[m17n/m17n-lib.git] / src / plist.c
index f8f27bb..01d52a2 100644 (file)
@@ -151,12 +151,9 @@ get_byte (MStream *st)
   return st->buffer[0];
 }
 
-#define GETC(st)       \
-  ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
+#define GETC(st) ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st))
 
-
-#define UNGETC(c, st)  \
-  (*--(st)->p = (c))
+#define UNGETC(c, st) (--((st)->p))
 
 /** Mapping table for reading a number.  Hexadecimal chars
     (0..9,A..F,a..F) are mapped to the corresponding numbers.
@@ -210,7 +207,7 @@ read_hexadesimal (MStream *st)
     for the next element.  */
 
 static MPlist *
-read_mtext_element (MPlist *plist, MStream *st)
+read_mtext_element (MPlist *plist, MStream *st, int skip)
 {
   unsigned char buffer[1024];
   int bufsize = 1024;
@@ -250,13 +247,17 @@ read_mtext_element (MPlist *plist, MStream *st)
            c = escape_mnemonic[c];
        }
 
-      buf[i++] = c;
+      if (! skip)
+       buf[i++] = c;
     }
 
-  MPLIST_SET_ADVANCE (plist, Mtext,
-                     mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
-  if (buf != buffer)
-    free (buf);
+  if (! skip)
+    {
+      MPLIST_SET_ADVANCE (plist, Mtext,
+                         mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1));
+      if (buf != buffer)
+       free (buf);
+    }
   return plist;
 }
 
@@ -289,7 +290,7 @@ read_character (MStream *st, int c)
     read the character C. */
 
 static MPlist *
-read_integer_element (MPlist *plist, MStream *st, int c)
+read_integer_element (MPlist *plist, MStream *st, int c, int skip)
 {
   int num;
 
@@ -329,7 +330,8 @@ read_integer_element (MPlist *plist, MStream *st, int c)
   else
     num = read_decimal (st, c);
 
-  MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
+  if (! skip)
+    MPLIST_SET_ADVANCE (plist, Minteger, (void *) num);
   return plist;
 }
 
@@ -337,7 +339,7 @@ read_integer_element (MPlist *plist, MStream *st, int c)
     for the next element.  */
 
 static MPlist *
-read_symbol_element (MPlist *plist, MStream *st)
+read_symbol_element (MPlist *plist, MStream *st, int skip)
 {
   unsigned char buffer[1024];
   int bufsize = 1024;
@@ -367,15 +369,19 @@ read_symbol_element (MPlist *plist, MStream *st)
            break;
          c = escape_mnemonic[c];
        }
-      buf[i++] = c;
+      if (! skip)
+       buf[i++] = c;
     }
 
-  buf[i] = 0;
-  MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
-  if (buf != buffer)
-    free (buf);
   if (c > ' ')
     UNGETC (c, st);
+  if (! skip)
+    {
+      buf[i] = 0;
+      MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf));
+      if (buf != buffer)
+       free (buf);
+    }
   return plist;
 }
 
@@ -387,10 +393,14 @@ read_symbol_element (MPlist *plist, MStream *st)
        '0'..'9', '-': integer
        '?': integer representing character code
        the other ASCII letters: symbol
-*/
+
+   If KEYS is not NULL, it is a plist contains target keys and stop
+   keys.  In this caes, read only a plist whose key has value 1 in
+   KEYS, and return NULL when we encounter a plist whose key has value
+   0 in KEYS while skipping any other elements.  */
 
 static MPlist *
-read_element (MPlist *plist, MStream *st)
+read_element (MPlist *plist, MStream *st, MPlist *keys)
 {
   int c;
 
@@ -411,18 +421,38 @@ read_element (MPlist *plist, MStream *st)
 
       MPLIST_NEW (pl);
       p = pl;
-      while ((p = read_element (p, st)));
-      MPLIST_SET_ADVANCE (plist, Mplist, pl);
+      p = read_element (p, st, NULL);
+      if (keys && p && MPLIST_SYMBOL_P (pl))
+       {
+         MPlist *p0 = keys;
+         MPLIST_FIND (p0, MPLIST_SYMBOL (pl));
+         if (! MPLIST_TAIL_P (p0) && ! MPLIST_VAL (p0))
+           {
+             M17N_OBJECT_UNREF (pl);
+             return NULL;
+           }
+         while ((p = read_element (p, st, NULL)));
+         if (! MPLIST_TAIL_P (p0))
+           MPLIST_SET_ADVANCE (plist, Mplist, pl);
+         else
+           M17N_OBJECT_UNREF (pl);
+       }
+      else
+       {
+         if (p)
+           while ((p = read_element (p, st, NULL)));
+         MPLIST_SET_ADVANCE (plist, Mplist, pl);
+       }
       return plist;
     }
   if (c == '"')
-    return read_mtext_element (plist, st);
+    return (read_mtext_element (plist, st, keys ? 1 : 0));
   if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#')
-    return read_integer_element (plist, st, c);
+    return (read_integer_element (plist, st, c, keys ? 1 : 0));
   if (c == EOF || c == ')')
     return NULL;
   UNGETC (c, st);
-  return read_symbol_element (plist, st);
+  return (read_symbol_element (plist, st, keys ? 1 : 0));
 }
 
 void
@@ -606,7 +636,7 @@ mplist__from_plist (MPlist *plist)
       key = MPLIST_SYMBOL (plist);
       plist = MPLIST_NEXT (plist);
       type = MPLIST_KEY (plist);
-      if (type->managing_key)
+      if (type->managing_key && MPLIST_VAL (plist))
        M17N_OBJECT_REF (MPLIST_VAL (plist));
       MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist));
       plist = MPLIST_NEXT (plist);
@@ -644,7 +674,7 @@ mplist__from_alist (MPlist *plist)
 
 
 MPlist *
-mplist__from_file (FILE *fp)
+mplist__from_file (FILE *fp, MPlist *keys)
 {
   MPlist *plist, *pl;
   MStream st;
@@ -654,7 +684,7 @@ mplist__from_file (FILE *fp)
   st.p = st.pend = st.buffer;
   MPLIST_NEW (plist);
   pl = plist;
-  while ((pl = read_element (pl, &st)));
+  while ((pl = read_element (pl, &st, keys)));
   return plist;
 }
 
@@ -703,7 +733,7 @@ mplist__from_string (unsigned char *str, int n)
   st.pend = str + n;
   MPLIST_NEW (plist);
   pl = plist;
-  while ((pl = read_element (pl, &st)));
+  while ((pl = read_element (pl, &st, NULL)));
   return plist;
 }
 
@@ -892,7 +922,8 @@ mplist_put (MPlist *plist, MSymbol key, void *val)
     {
       if (! MPLIST_TAIL_P (plist))
        M17N_OBJECT_UNREF (MPLIST_VAL (plist));
-      M17N_OBJECT_REF (val);
+      if (val)
+       M17N_OBJECT_REF (val);
     }
   MPLIST_SET (plist, key, val);
   return plist;
@@ -972,7 +1003,7 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
   if (key == Mnil)
     MERROR (MERROR_PLIST, NULL);
   MPLIST_FIND (plist, Mnil);
-  if (key->managing_key)
+  if (val && key->managing_key)
     M17N_OBJECT_REF (val);
   MPLIST_KEY (plist) = key;
   MPLIST_VAL (plist) = val;
@@ -983,10 +1014,10 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
 /*=*/
 
 /***en
-    @brief Push a property to a property list.
+    @brief Add a property at the beginning of a property list.
 
-    The mplist_push () function pushes at the top of property list
-     $PLIST a property whose key is $KEY and value is $VAL.
+    The mplist_push () function inserts at the beginning of property
+    list $PLIST a property whose key is $KEY and value is $VAL.
 
     If $KEY is a managing key, $VAL must be a managed object.  In this
     case, the reference count of $VAL is incremented by one.
@@ -995,10 +1026,10 @@ mplist_add (MPlist *plist, MSymbol key, void *val)
     If the operation was successful, this function returns $PLIST.
     Otherwise, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥×¥Ã¥·¥å¤¹¤ë.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤Ë¥×¥í¥Ñ¥Æ¥£¤òÁÞÆþ¤¹¤ë.
 
-    ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤Î¾å¤Ë¤Ë¥­¡¼¤¬ $KEY 
-    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¥×¥Ã¥·¥å¤¹¤ë¡£
+    ´Ø¿ô mplist_push () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Ë¥­¡¼¤¬ $KEY 
+    ¤ÇÃͤ¬ $VAL ¤Ç¤¢¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÁÞÆþ¤¹¤ë¡£
 
     $KEY ¤¬´ÉÍý¥­¡¼¤Ê¤é¤Ð¡¢$VAL ¤Ï´ÉÍý²¼¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
     ¤³¤Î¾ì¹ç¡¢$VAL ¤Î»²¾È¿ô¤Ï 1 Áý¤ä¤µ¤ì¤ë¡£
@@ -1017,9 +1048,9 @@ mplist_push (MPlist *plist, MSymbol key, void *val)
   MPLIST_NEW (pl);
   MPLIST_KEY (pl) = MPLIST_KEY (plist);
   MPLIST_VAL (pl) = MPLIST_VAL (plist);
-  pl->next = plist->next;
+  MPLIST_NEXT (pl) = MPLIST_NEXT (plist);
   plist->next = pl;
-  if (key->managing_key)
+  if (val && key->managing_key)
     M17N_OBJECT_REF (val);
   MPLIST_KEY (plist) = key;
   MPLIST_VAL (plist) = val;
@@ -1029,24 +1060,24 @@ mplist_push (MPlist *plist, MSymbol key, void *val)
 /*=*/
 
 /***en
-    @brief Pop a property from a property list.
+    @brief Remove a property at the beginning of a property list.
 
-    The mplist_pop () function pops the topmost property from property
-    list $PLIST.  As a result, the key and value of $PLIST becomes
-    those of the next of $PLIST.
+    The mplist_pop () function removes a property at the beginning of
+    property list $PLIST.  As a result, the second key and value of
+    the original $PLIST become the first of those of the new $PLIST.
 
     @return
     If the operation was successful, this function return the value of
     the just popped property.  Otherwise, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ý¥Ã¥×¤¹¤ë.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ÎÀèƬ¤«¤é¥×¥í¥Ñ¥Æ¥£¤òºï½ü¤¹¤ë.
 
-    ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤«¤éºÇ¾å°Ì¤Î¥×¥í¥Ñ¥Æ¥£
-    ¤ò¥Ý¥Ã¥×¤¹¤ë¡£·ë²Ì¤È¤·¤Æ $PLIST ¤Î¥­¡¼¤ÈÃͤϠ$PLIST ¤Î¼¡¤Î¥­¡¼¤ÈÃÍ
-    ¤Ë¤Ê¤ë¡£
+    ´Ø¿ô mplist_pop () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ÎÀèƬ¤Î¥×¥í¥Ñ¥Æ¥£¤ò
+    ºï½ü¤¹¤ë¡£·ë²Ì¤È¤·¤Æ¡¢¸µ¤Î $PLIST ¤Î2ÈÖÌܤΥ­¡¼¤ÈÃͤ¬¡¢¿·¤·¤¤ 
+    $PLIST ¤ÎÀèƬ¤Î¥­¡¼¤ÈÃͤˤʤ롣
 
     @return 
-    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Ý¥Ã¥×¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
+    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ïºï½ü¤µ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£¤½¤¦
     ¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤¹¡£  */
 
 void *
@@ -1058,14 +1089,14 @@ mplist_pop (MPlist *plist)
   if (MPLIST_TAIL_P (plist))
     return NULL;
   val = MPLIST_VAL (plist);
-  next = plist->next;
+  next = MPLIST_NEXT (plist);
   MPLIST_KEY (plist) = MPLIST_KEY (next);
   MPLIST_VAL (plist) = MPLIST_VAL (next);
   if (MPLIST_KEY (plist) != Mnil
       && MPLIST_KEY (plist)->managing_key
       && MPLIST_VAL (plist))
     M17N_OBJECT_REF (MPLIST_VAL (plist));
-  plist->next = next->next;
+  MPLIST_NEXT (plist) = MPLIST_NEXT (next);
   if (plist->next)
     M17N_OBJECT_REF (plist->next);
   M17N_OBJECT_UNREF (next);
@@ -1084,7 +1115,7 @@ mplist_pop (MPlist *plist)
     If $KEY is @c Mnil, it returns a sublist of $PLIST whose
     first element is the last one of $PLIST.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥­¡¼¤ò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤Î¥­¡¼¤ò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
 
     ´Ø¿ô mplist_find_by_key () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤éõ
     ¤·¤Æ¡¢¥­¡¼¤¬ $KEY ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
@@ -1112,7 +1143,7 @@ mplist_find_by_key (MPlist *plist, MSymbol key)
     property is found, a sublist of $PLIST whose first element is the
     found one is returned.  Otherwise, @c NULL is returned.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥ª¥Ö¥¸¥§¥¯¥È¤òõ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃ椫¤é»ØÄê¤ÎÃͤò»ý¤Ä¥×¥í¥Ñ¥Æ¥£¤òõ¤¹.
 
     ´Ø¿ô mplist_find_by_value () ¤Ï¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST ¤ò»Ï¤á¤«¤é
     Ãµ¤·¤Æ¡¢Ãͤ¬ $VAL ¤Ç¤¢¤ë¥×¥í¥Ñ¥Æ¥£¤ò¸«¤Ä¤±¤ë¡£¸«¤Ä¤«¤ì¤Ð¡¢¤½¤Î¥×¥í
@@ -1156,7 +1187,7 @@ mplist_next (MPlist *plist)
 /***en
     @brief Set the first property in a property list.
 
-    The mplist_set () function sets the key and value of the first
+    The mplist_set () function sets the key and the value of the first
     property in property list $PLIST to $KEY and $VALUE, respectively.
     See the documentation of mplist_add () for the restriction on $KEY
     and $VAL.
@@ -1185,7 +1216,7 @@ mplist_set (MPlist *plist, MSymbol key, void * val)
          key = MPLIST_KEY (plist);
          M17N_OBJECT_UNREF (MPLIST_NEXT (plist));
          MPLIST_KEY (plist) = Mnil;
-         if (key->managing_key && MPLIST_VAL (plist))
+         if (key->managing_key)
            M17N_OBJECT_UNREF (MPLIST_VAL (plist));
          plist->next = NULL;
        }
@@ -1193,10 +1224,9 @@ mplist_set (MPlist *plist, MSymbol key, void * val)
   else
     {
       if (! MPLIST_TAIL_P (plist)
-         && MPLIST_KEY (plist)->managing_key
-         && MPLIST_VAL (plist))
+         && MPLIST_KEY (plist)->managing_key)
        M17N_OBJECT_UNREF (MPLIST_VAL (plist));
-      if (key->managing_key)
+      if (val && key->managing_key)
        M17N_OBJECT_REF (val);
       MPLIST_SET (plist, key, val);
     }
@@ -1255,7 +1285,7 @@ mplist_key (MPlist *plist)
     property in property list  $PLIST.  If the length of $PLIST
     is zero, it returns @c NULL.  */
 /***ja
-    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹.
+    @brief ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥ÈÃæ¤ÎºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
 
     ´Ø¿ô mplist_value () ¤Ï¡¢¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È $PLIST Ãæ¤Î
     ºÇ½é¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£$PLIST ¤ÎŤµ¤¬ 0 ¤Ê¤é¤Ð¡¢ @c Mnil ¤ò