*** empty log message ***
[m17n/m17n-lib-cs.git] / MPlist.cs
index ffdea57..f54b47f 100644 (file)
--- a/MPlist.cs
+++ b/MPlist.cs
@@ -1,22 +1,35 @@
 using System;
+using System.Collections;
 using M17N.Core;
 
 namespace M17N.Core
 {
-  public class MPlist
+  public struct MProperty
   {
-    private MSymbol key;
-    private object val;
+    internal MSymbol key;
+    internal object val;
+
+    public MSymbol Key { get { return this.key;} }
+    public object Val { get { return this.val; } }
+
+    public MProperty (MSymbol key, object val)
+      {
+       this.key = key;
+       this.val = val;
+      }
+  }
+
+  public class MPlist : IEnumerable
+  {
+    private MProperty prop;
     private MPlist next;
 
     public MPlist ()
     {
-      key = null;
-      val = null;
-      next = null;
+      prop = new MProperty (MSymbol.nil, null);
     }
 
-    public bool tailp { get { return (object) key == null; } }
+    public bool tailp { get { return prop.key == MSymbol.nil; } }
 
     public new string ToString ()
     {
@@ -24,11 +37,11 @@ namespace M17N.Core
 
       for (MPlist p = this; ! p.tailp; p = p.next)
        {
-         str += (p == this ? "(" : " ") + p.key.ToString () + ":";
-         if (p.val is MSymbol)
-           str += ((MSymbol) p.val).ToString ();
-         else if (p.val is MPlist)
-           str += ((MPlist) p.val).ToString ();
+         str += (p == this ? "(" : " ") + p.prop.key.ToString () + ":";
+         if (p.prop.val is MSymbol)
+           str += ((MSymbol) p.prop.val).ToString ();
+         else if (p.prop.val is MPlist)
+           str += ((MPlist) p.prop.val).ToString ();
        }
       return str + ")";
     }
@@ -38,8 +51,8 @@ namespace M17N.Core
       if ((object) key == null)
        return null;
       for (MPlist p = this; ! p.tailp; p = p.next)
-       if (p.key == key)
-         return p.val;
+       if (p.prop.key == key)
+         return p.prop.val;
       return null;
     }
 
@@ -48,18 +61,18 @@ namespace M17N.Core
       MPlist p;
 
       for (p = this; ! p.tailp; p = p.next)
-       if (p.key == key)
+       if (p.prop.key == key)
          {
            if (val != null)
-             p.val = val;
+             p.prop.val = val;
            else
              p.pop ();
            return val;
          }
       if (val != null)
        {
-         p.key = key;
-         p.val = val;
+         p.prop.key = key;
+         p.prop.val = val;
          p.next = new MPlist ();
        }
       return val;
@@ -69,11 +82,11 @@ namespace M17N.Core
     {
       MPlist p = new MPlist ();
 
-      p.key = this.key;
-      p.val = this.val;
+      p.prop.key = this.prop.key;
+      p.prop.val = this.prop.val;
       p.next = this.next;
-      this.key = key;
-      this.val = val;
+      this.prop.key = key;
+      this.prop.val = val;
       this.next = p;
 
       return val;
@@ -84,10 +97,10 @@ namespace M17N.Core
       if (tailp)
        return null;
 
-      object val = this.val;
+      object val = this.prop.val;
 
-      this.key = this.next.key;
-      this.val = this.next.val;
+      this.prop.key = this.next.prop.key;
+      this.prop.val = this.next.prop.val;
       this.next = this.next.next;
       return val;
     }
@@ -99,11 +112,62 @@ namespace M17N.Core
       for (p = this; ! p.tailp; p = p.next);
       if (val != null)
        {
-         p.key = key;
-         p.val = val;
+         p.prop.key = key;
+         p.prop.val = val;
          p.next = new MPlist ();
        }
       return val;
     }
+
+    public MPlist find (MSymbol key)
+    {
+      for (MPlist p = this; ! p.tailp; p = p.next)
+       if (p.prop.key == key)
+         return p;
+      return null;
+    }
+
+    // Implement IEnumerable interface.
+
+    public virtual IEnumerator GetEnumerator ()
+    {
+      return new Enumerator (this);
+    }
+
+    private class Enumerator : IEnumerator
+    {
+      private MPlist plist;
+      private MPlist current;
+
+      internal Enumerator (MPlist plist)
+       {
+         this.plist = plist;
+       }
+
+      public object Current
+      {
+       get {
+         if (current == null || current.tailp)
+           throw new InvalidOperationException ();
+         return current;
+       }
+      }
+
+      public void Reset ()
+      {
+       current = null;
+      }
+
+      public bool MoveNext ()
+      {
+       if (current == null)
+         current = plist;
+       else if (current.tailp)
+         return false;
+       else
+         current = current.next;
+       return true;
+      }
+    }
   }
 }