*** empty log message ***
[m17n/m17n-lib-cs.git] / MPlist.cs
index 4212184..3c9b140 100644 (file)
--- a/MPlist.cs
+++ b/MPlist.cs
@@ -18,8 +18,9 @@ namespace M17N.Core
        Val = null;
       }
 
-    public MPlist (MStreamReader reader)
+    public MPlist (FileStream stream)
       {
+       MStreamReader reader = new MStreamReader (stream);
        MSymbol key;
        object val;
        bool result = reader.ReadElement (out key, out val);
@@ -30,6 +31,114 @@ namespace M17N.Core
          next = new MPlist (reader);
       }
 
+    public MPlist (FileStream stream, int count)
+      {
+       MStreamReader reader = new MStreamReader (stream);
+       MSymbol key;
+       object val;
+       bool result = reader.ReadElement (out key, out val);
+
+       Key = key;
+       Val = val;
+       if (result && --count > 0)
+         next = new MPlist (reader, count);
+       else
+         next = new MPlist ();
+      }
+
+    public MPlist (FileStream stream, MSymbol target, MSymbol stop)
+      {
+       MStreamReader reader = new MStreamReader (stream);
+       MSymbol key;
+       object val;
+       bool result;
+
+       Key = MSymbol.nil;
+       Val = null;
+       while (true)
+         {
+           result = reader.ReadElement (out key, out val);
+           if (! result)
+             return;
+           if (key == MSymbol.plist)
+             {
+               MPlist plist = (MPlist) val;
+
+               if (plist.IsSymbol)
+                 {
+                   if (plist.Symbol == stop)
+                     return;
+                   if (plist.Symbol == target)
+                     {
+                       Key = target;
+                       Val = val;
+                       next = new MPlist ();
+                       return;
+                     }
+                 }
+             }
+         }
+      }
+
+    private MPlist (MStreamReader reader)
+      {
+       MSymbol key;
+       object val;
+       bool result = reader.ReadElement (out key, out val);
+
+       Key = key;
+       Val = val;
+       if (result)
+         next = new MPlist (reader);
+      }
+
+    private MPlist (MStreamReader reader, int count)
+      {
+       MSymbol key;
+       object val;
+       bool result = reader.ReadElement (out key, out val);
+
+       Key = key;
+       Val = val;
+       if (result && --count > 0)
+         next = new MPlist (reader, count);
+       else
+         next = new MPlist ();
+      }
+
+    private MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
+      {
+       MSymbol key;
+       object val;
+       bool result;
+
+       Key = MSymbol.nil;
+       Val = null;
+       while (true)
+         {
+           result = reader.ReadElement (out key, out val);
+           if (! result)
+             return;
+           if (key == MSymbol.plist)
+             {
+               MPlist plist = (MPlist) val;
+
+               if (plist.IsSymbol)
+                 {
+                   if (plist.Symbol == stop)
+                     return;
+                   if (plist.Symbol == target)
+                     {
+                       Key = target;
+                       Val = val;
+                       next = new MPlist ();
+                       return;
+                     }
+                 }
+             }
+         }
+      }
+
     private MPlist (MSymbol key, object val)
       {
        Key = key;
@@ -39,6 +148,16 @@ namespace M17N.Core
     public bool IsEmpty { get { return next == null; } }
     public MPlist Next { get { return next; } }
 
+    internal bool IsSymbol { get { return Key == MSymbol.symbol; } }
+    internal bool IsMText { get { return Key == MSymbol.mtext; } }
+    internal bool IsPlist { get { return Key == MSymbol.plist; } }
+    internal bool IsInteger { get { return Key == MSymbol.integer; } }
+
+    internal MSymbol Symbol { get { return (MSymbol) Val; } }
+    internal MText Text { get { return (MText) Val; } }
+    internal MPlist Plist { get { return (MPlist) Val; } }
+    internal int Integer { get { return (int) Val; } }
+
     public int Count
     {
       get
@@ -72,7 +191,10 @@ namespace M17N.Core
                && p.Key != MSymbol.plist
                && p.Key != MSymbol.mtext)
              str += p.Key + ":";
-           str += p.Val;
+           if (p.Key == MSymbol.mtext)
+             str += "\"" + p.Val + "\"";
+           else
+             str += p.Val;
          }
        return str + ")";
     }
@@ -99,6 +221,14 @@ namespace M17N.Core
       return find (key).Val;
     }
 
+    internal MPlist Assq (MSymbol key)
+    {
+      foreach (MPlist p in this)
+       if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key)
+         return p;
+      return null;
+    }
+
     private delegate MPlist MPlistDelegate (MSymbol key, object val);
 
     private MPlist mplist_op (MPlistDelegate op, object val)
@@ -184,6 +314,14 @@ namespace M17N.Core
       return p.Push (key, val);
     }
 
+    public MPlist Clear ()
+    {
+      Key = MSymbol.nil;
+      Val = null;
+      next = null;
+      return this;
+    }
+
     // Implement IEnumerable interface.
     //   foreach (MPlist p in plist) { ... }
 
@@ -225,222 +363,220 @@ namespace M17N.Core
        return (! current.IsEmpty);
       }
     }
-  }
-
-  public class MStreamReader : StreamReader
-  {
-    private static char[] escaped_char = new char[128];
-    private static int[] hexadecimal = new int[128];
 
-    public MStreamReader (Stream stream) : base (stream)
-      {
-      }
-
-    static MStreamReader ()
-      {
-       for (int i = 0; i < 128; i++)
-         escaped_char[i] = (char) i;
-       escaped_char['e'] = (char) 27;
-       escaped_char['b'] = '\b';
-       escaped_char['f'] = '\f';
-       escaped_char['n'] = '\n';
-       escaped_char['r'] = '\r';
-       escaped_char['t'] = '\t';
-       escaped_char['\\'] = '\\';
-       for (int i = 0; i < 128; i++)
-         hexadecimal[i] = -1;
-       for (int i = '0'; i <= '9'; i++)
-         hexadecimal[i] = i - '0';
-       for (int i = 'A'; i <= 'F'; i++)
-         hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
-      }
-
-    internal int PeekChar ()
+    private class MStreamReader : StreamReader
     {
-      bool comment = false;
-      int c;
+      private static char[] escaped_char = new char[128];
+      private static int[] hexadecimal = new int[128];
 
-      while ((c = Peek ()) != -1)
+      public MStreamReader (Stream stream) : base (stream)
        {
-         if (comment)
-           {
-             if ((c = Read ()) == '\n')
-               comment = false;
-           }
-         else
-           {
-             if (c == ';')
-               comment = true;
-             else if (c != ' ' && c != '\t' && c != '\n')
-               return c;
-             Read ();
-           }
        }
-      return c;
-    }
-
-    internal int ReadHexadecimal ()
-    {
-      int i = 0, c;
 
-      while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
+      static MStreamReader ()
        {
-         Read ();
-         i = (i * 16) + c;
+         for (int i = 0; i < 128; i++)
+           escaped_char[i] = (char) i;
+         escaped_char['e'] = (char) 27;
+         escaped_char['b'] = '\b';
+         escaped_char['f'] = '\f';
+         escaped_char['n'] = '\n';
+         escaped_char['r'] = '\r';
+         escaped_char['t'] = '\t';
+         escaped_char['\\'] = '\\';
+         for (int i = 0; i < 128; i++)
+           hexadecimal[i] = -1;
+         for (int i = '0'; i <= '9'; i++)
+           hexadecimal[i] = i - '0';
+         for (int i = 'A'; i <= 'F'; i++)
+           hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
        }
-      return i;
-    }
 
-    internal int ReadInteger ()
-    {
-      int i = 0, c;
+      private int PeekChar ()
+      {
+       bool comment = false;
+       int c;
 
-      while ((c = Peek ()) >= '0' && c <= '9')
-       i = (i * 10) + (Read () - '0');
-      return i;
-    }
+       while ((c = Peek ()) != -1)
+         {
+           if (comment)
+             {
+               if ((c = Read ()) == '\n')
+                 comment = false;
+             }
+           else
+             {
+               if (c == ';')
+                 comment = true;
+               else if (c != ' ' && c != '\t' && c != '\n')
+                 return c;
+               Read ();
+             }
+         }
+       return c;
+      }
 
-    internal int ReadChar ()
-    {
-      int c = Read ();
+      private int ReadHexadecimal ()
+      {
+       int i = 0, c;
 
-      if (c == '\\')
-       {
-         c = Read ();
-         if (c == -1)
-           return -1;
-         if (c == 'x' || c == 'u')
-           return ReadHexadecimal ();
-         if (c < 128)
-           c = escaped_char[c];
-       }
-      return c;
-    }
+       while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
+         {
+           Read ();
+           i = (i * 16) + c;
+         }
+       return i;
+      }
 
-    internal MText ReadMtext ()
-    {
-      MText mt = new MText ();
-      int c;
+      private int ReadInteger ()
+      {
+       int i = 0, c;
 
-      while ((c = Peek ()) != -1 && c != '"')
-       {
-         if (c == '\\')
-           {
-             c = ReadChar ();
-             if (Peek () == '\n')
-               {
-                 ReadChar ();
-                 continue;
-               }
-             if (c == -1)
-               {
-                 mt.Cat ('\\');
-                 break;
-               }
-             mt.Cat (c);
-           }
-         else
-           mt.Cat (Read ());
-       }
-      if (c == '"')
-       Read ();
-      return mt;
-    }
+       while ((c = Peek ()) >= '0' && c <= '9')
+         i = (i * 10) + (Read () - '0');
+       return i;
+      }
 
-    internal string ReadSymbolName ()
-    {
-      int c = Peek ();
+      private int ReadChar ()
+      {
+       int c = Read ();
 
-      if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
-       return "";
-      Read ();
-      if (c == '\\')
-       {
-         c = Read ();
-         if (c == -1)
-           c = '\\';
-       }
-      return (char) c + ReadSymbolName ();
-    }
+       if (c == '\\')
+         {
+           c = Read ();
+           if (c == -1)
+             return -1;
+           if (c == 'x' || c == 'u')
+             return ReadHexadecimal ();
+           if (c < 128)
+             c = escaped_char[c];
+         }
+       return c;
+      }
 
-    internal bool ReadElement (out MSymbol key, out object val)
-    {
-      int c = PeekChar ();
+      private MText ReadMtext ()
+      {
+       MText mt = new MText ();
+       int c;
 
-      if (c == '(')
-       {
-         Read ();
-         val = new MPlist (this);
-         key = MSymbol.plist;
-       }
-      else if (c == '"')
-       {
+       while ((c = Peek ()) != -1 && c != '"')
+         {
+           if (c == '\\')
+             {
+               c = ReadChar ();
+               if (Peek () == '\n')
+                 {
+                   ReadChar ();
+                   continue;
+                 }
+               if (c == -1)
+                 {
+                   mt.Cat ('\\');
+                   break;
+                 }
+               mt.Cat (c);
+             }
+           else
+             mt.Cat (Read ());
+         }
+       if (c == '"')
          Read ();
-         val = ReadMtext ();
-         key = MSymbol.mtext;
-       }
-      else if (c >= '0' && c <= '9')
-       {
-         int i = ReadInteger ();
+       return mt;
+      }
 
-         val = i;
-         key = MSymbol.integer;
-       }
-      else if (c == '-')
-       {
-         Read ();
-         c = Peek ();
-         if (c >= '0' && c <= '9')
-           {
-             int i = ReadInteger ();
-             val = - i;
-             key = MSymbol.integer;
-           }
-         else
-           {
-             string str = ReadSymbolName ();
-
-             val = new MSymbol ("-" + str);
-             key = MSymbol.symbol;
-           }
-       }
-      else if (c == '?')
-       {
-         Read ();
-         val = ReadChar ();
-         key = MSymbol.integer;
-       }
-      else if (c == '#')
-       {
-         Read ();
-         if ((c = Peek ()) == 'x' || c == 'u')
-           {
-             Read ();
-             val = ReadHexadecimal ();
-             key = MSymbol.integer;
-           }
-         else
-           {
-             string str = ReadSymbolName ();
-
-             val = new MSymbol ("#" + (char) c + str);
-             key = MSymbol.symbol;
-           }
-       }
-      else if (c == -1 || c == ')')
-       {
-         if (c == ')')
+      private string ReadSymbolName ()
+      {
+       int c = Peek ();
+
+       if (c == -1 || c == '(' || c == ')' || c == ' ' || c == '\n' || c == '"')
+         return "";
+       Read ();
+       if (c == '\\')
+         {
+           c = Read ();
+           if (c == -1)
+             c = '\\';
+         }
+       return (char) c + ReadSymbolName ();
+      }
+
+      public bool ReadElement (out MSymbol key, out object val)
+      {
+       int c = PeekChar ();
+
+       if (c == '(')
+         {
            Read ();
-         val = null;
-         key = MSymbol.nil;
-         return false;
-       }
-      else
-       {
-         val = new MSymbol (ReadSymbolName ());
-         key = MSymbol.symbol;
-       }
-      return true;
+           val = new MPlist (this);
+           key = MSymbol.plist;
+         }
+       else if (c == '"')
+         {
+           Read ();
+           val = ReadMtext ();
+           key = MSymbol.mtext;
+         }
+       else if (c >= '0' && c <= '9')
+         {
+           int i = ReadInteger ();
+
+           val = i;
+           key = MSymbol.integer;
+         }
+       else if (c == '-')
+         {
+           Read ();
+           c = Peek ();
+           if (c >= '0' && c <= '9')
+             {
+               int i = ReadInteger ();
+               val = - i;
+               key = MSymbol.integer;
+             }
+           else
+             {
+               string str = ReadSymbolName ();
+
+               val = MSymbol.Of ("-" + str);
+               key = MSymbol.symbol;
+             }
+         }
+       else if (c == '?')
+         {
+           Read ();
+           val = ReadChar ();
+           key = MSymbol.integer;
+         }
+       else if (c == '#')
+         {
+           Read ();
+           if ((c = Peek ()) == 'x' || c == 'u')
+             {
+               Read ();
+               val = ReadHexadecimal ();
+               key = MSymbol.integer;
+             }
+           else
+             {
+               val = MSymbol.Of ("#" + (char) c + ReadSymbolName ());
+               key = MSymbol.symbol;
+             }
+         }
+       else if (c == -1 || c == ')')
+         {
+           if (c == ')')
+             Read ();
+           val = null;
+           key = MSymbol.nil;
+           return false;
+         }
+       else
+         {
+           val = MSymbol.Of (ReadSymbolName ());
+           key = MSymbol.symbol;
+         }
+       return true;
+      }
     }
   }
 }