*** empty log message ***
[m17n/m17n-lib-cs.git] / MPlist.cs
index 480c9d2..57005c9 100644 (file)
--- a/MPlist.cs
+++ b/MPlist.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.IO;
 using M17N;
 using M17N.Core;
@@ -8,25 +9,36 @@ namespace M17N.Core
 {
   public class MPlist : IEnumerable
   {
-    public MSymbol Key;
-    public object Val;
-    private MPlist next;
+    public MSymbol key;
+    public object val;
+    public MPlist next;
+
+    public MSymbol Key { get { return key; } }
+    public object Val { get { return val; } }
+    public MPlist Next { get { return next; } }
+
+    private static List<MSymbol> wf_keys;
+
+    static MPlist ()
+      {
+       wf_keys = new List<MSymbol> ();
+       wf_keys.Add (MSymbol.symbol);
+       wf_keys.Add (MSymbol.mtext);
+       wf_keys.Add (MSymbol.plist);
+       wf_keys.Add (MSymbol.integer);
+      }
 
     public MPlist ()
       {
-       Key = MSymbol.nil;
-       Val = null;
+       key = MSymbol.nil;
+       val = null;
       }
 
     public MPlist (FileStream stream)
       {
        MStreamReader reader = new MStreamReader (stream);
-       MSymbol key;
-       object val;
        bool result = reader.ReadElement (out key, out val);
 
-       Key = key;
-       Val = val;
        if (result)
          next = new MPlist (reader);
       }
@@ -34,35 +46,60 @@ namespace M17N.Core
     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 stop)
+      {
+       MStreamReader reader = new MStreamReader (stream);
+       bool result;
+
+       key = MSymbol.nil;
+       val = null;
+       while (true)
+         {
+           MSymbol this_key;
+           object this_val;
+
+           result = reader.ReadElement (out this_key, out this_val);
+           if (! result)
+             return;
+           if (this_key == MSymbol.plist)
+             {
+               MPlist plist = (MPlist) this_val;
+
+               if (plist.IsSymbol && plist.Symbol == stop)
+                 return;
+             }
+           key = this_key;
+           val = this_val;
+           next = new MPlist (reader, stop);
+         }
+      }
+
     public MPlist (FileStream stream, MSymbol target, MSymbol stop)
       {
        MStreamReader reader = new MStreamReader (stream);
-       MSymbol key;
-       object val;
        bool result;
 
-       Key = MSymbol.nil;
-       Val = null;
+       key = MSymbol.nil;
+       val = null;
        while (true)
          {
-           result = reader.ReadElement (out key, out val);
+           MSymbol this_key;
+           object this_val;
+
+           result = reader.ReadElement (out this_key, out this_val);
            if (! result)
              return;
-           if (key == MSymbol.plist)
+           if (this_key == MSymbol.plist)
              {
-               MPlist plist = (MPlist) val;
+               MPlist plist = (MPlist) this_val;
 
                if (plist.IsSymbol)
                  {
@@ -70,8 +107,8 @@ namespace M17N.Core
                      return;
                    if (plist.Symbol == target)
                      {
-                       Key = target;
-                       Val = val;
+                       key = target;
+                       val = this_val;
                        next = new MPlist ();
                        return;
                      }
@@ -82,46 +119,77 @@ namespace M17N.Core
 
     internal 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 stop)
+      {
+       bool result;
+       MPlist next_plist = null;
+
+       key = MSymbol.nil;
+       val = null;
+       while (true)
+         {
+           MSymbol this_key;
+           object this_val;
+
+           result = reader.ReadElement (out this_key, out this_val);
+           if (! result)
+             return;
+           if (this_key == MSymbol.plist)
+             {
+               MPlist plist = (MPlist) this_val;
+
+               if (plist.IsSymbol && plist.Symbol == stop)
+                 return;
+             }
+           if (next_plist == null)
+             {
+               key = this_key;
+               val = this_val;
+               next = next_plist = new MPlist ();
+             }
+           else
+             {
+               next_plist.key = this_key;
+               next_plist.val = this_val;
+               next_plist.next = new MPlist ();
+               next_plist = next_plist.next;
+             }
+         }
+      }
+
     private MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
       {
-       MSymbol key;
-       object val;
        bool result;
 
-       Key = MSymbol.nil;
-       Val = null;
+       key = MSymbol.nil;
+       val = null;
        while (true)
          {
-           result = reader.ReadElement (out key, out val);
+           MSymbol this_key;
+           object this_val;
+
+           result = reader.ReadElement (out this_key, out this_val);
            if (! result)
              return;
-           if (key == MSymbol.plist)
+           if (this_key == MSymbol.plist)
              {
-               MPlist plist = (MPlist) val;
+               MPlist plist = (MPlist) this_val;
 
                if (plist.IsSymbol)
                  {
@@ -129,8 +197,8 @@ namespace M17N.Core
                      return;
                    if (plist.Symbol == target)
                      {
-                       Key = target;
-                       Val = val;
+                       key = target;
+                       val = this_val;
                        next = new MPlist ();
                        return;
                      }
@@ -139,24 +207,23 @@ namespace M17N.Core
          }
       }
 
-    private MPlist (MSymbol key, object val)
+    protected MPlist (MSymbol key, object val)
       {
-       Key = key;
-       Val = val;
+       this.key = key;
+       this.val = val;
       }
 
     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; } }
+    public bool IsSymbol { get { return Key == MSymbol.symbol; } }
+    public bool IsMText { get { return Key == MSymbol.mtext; } }
+    public bool IsPlist { get { return Key == MSymbol.plist; } }
+    public 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 MSymbol Symbol { get { return (MSymbol) val; } }
+    public MText Text { get { return (MText) val; } }
+    public MPlist Plist { get { return (MPlist) val; } }
+    public int Integer { get { return (int) val; } }
 
     public int Count
     {
@@ -169,12 +236,21 @@ namespace M17N.Core
        }
     }
 
+    public MPlist this[int i]
+    {
+      get {
+       MPlist p;
+       for (p = this; ! p.IsEmpty && i > 0; i--, p = p.next);
+       return (i == 0 ? p : null);
+      }
+    }
+
     public MPlist Clone ()
     {
       MPlist plist = new MPlist (), pl = plist;
 
       for (MPlist p = this; p.next != null; p = p.next)
-       pl = pl.Add (p.Key, p.Val);
+       pl = pl.Add (p.key, p.val);
       return plist;
     }
 
@@ -186,15 +262,12 @@ namespace M17N.Core
          {
            if (p != this)
              str += " ";
-           if (p.Key != MSymbol.symbol
-               && p.Key != MSymbol.integer
-               && p.Key != MSymbol.plist
-               && p.Key != MSymbol.mtext)
-             str += p.Key + ":";
-           if (p.Key == MSymbol.mtext)
-             str += "\"" + p.Val + "\"";
+           if (! wf_keys.Contains (p.key))
+             str += p.key + ":";
+           if (p.key == MSymbol.mtext)
+             str += "\"" + p.val + "\"";
            else
-             str += p.Val;
+             str += p.val;
          }
        return str + ")";
     }
@@ -204,7 +277,7 @@ namespace M17N.Core
       MPlist p;
 
       for (p = this; ! p.IsEmpty; p = p.next)
-       if (p.Key == key)
+       if (p.key == key)
          break;
       return p;
     }
@@ -218,7 +291,7 @@ namespace M17N.Core
 
     public object Get (MSymbol key)
     {
-      return find (key).Val;
+      return find (key).val;
     }
 
     internal MPlist Assq (MSymbol key)
@@ -251,7 +324,10 @@ namespace M17N.Core
       if (IsEmpty)
        Push (key, val);
       else
-       Val = val;
+       {
+         this.key = key;
+         this.val = val;
+       }
       return this;
     }
 
@@ -272,11 +348,11 @@ namespace M17N.Core
 
     public MPlist Push (MSymbol key, object val)
     {
-      MPlist p = new MPlist (Key, Val);
+      MPlist p = new MPlist (this.key, this.val);
 
       p.next = this.next;
-      Key = key;
-      Val = val;
+      this.key = key;
+      this.val = val;
       next = p;
       return this;
     }
@@ -288,22 +364,22 @@ namespace M17N.Core
 
     public object Pop (out MSymbol key)
     {
-      key = Key;
+      key = this.key;
       if (IsEmpty)
        return null;
 
-      object val = Val;
+      object this_val = val;
 
-      Key = next.Key;
-      Val = next.Val;
+      this.key = next.key;
+      this.val = next.val;
       next = next.next;
-      return val;
+      return this_val;
     }
 
     public object Pop ()
     {
-      MSymbol key;
-      return Pop (out key);
+      MSymbol temp;
+      return Pop (out temp);
     }
 
     public MPlist Add (MSymbol key, object val)
@@ -314,10 +390,19 @@ namespace M17N.Core
       return p.Push (key, val);
     }
 
+    public MPlist Cons (MSymbol key, object val)
+    {
+      MPlist plist = new MPlist ();
+      plist.key = key;
+      plist.val = val;
+      plist.next = this;
+      return plist;
+    }
+
     public MPlist Clear ()
     {
-      Key = MSymbol.nil;
-      Val = null;
+      key = MSymbol.nil;
+      val = null;
       next = null;
       return this;
     }
@@ -606,7 +691,7 @@ namespace M17N.Core
          val = new MPlist (this);
          key = MSymbol.plist;
        }
-      else if (c == '"' || c == '\\')
+      else if (c == '"')
        {
          MText mt;
          ReadMText (out mt);