*** empty log message ***
[m17n/m17n-lib-cs.git] / MPlist.cs
1 using System;
2 using System.Collections;
3 using M17N.Core;
4
5 namespace M17N.Core
6 {
7   public class MPlist : IEnumerable
8   {
9     public MSymbol Key;
10     public object Val;
11     private MPlist next;
12
13     public MPlist ()
14       {
15         Key = MSymbol.nil;
16         Val = null;
17       }
18
19     private MPlist (MSymbol key, object val)
20       {
21         Key = key;
22         Val = val;
23       }
24
25     public bool IsEmpty { get { return next == null; } }
26     public MPlist Next { get { return next; } }
27
28     public int Count
29     {
30       get
31         {
32           int i = 0;
33
34           for (MPlist p = this; p.next != null; i++, p = p.next);
35           return i;
36         }
37     }
38
39     public MPlist Clone ()
40     {
41       MPlist plist = new MPlist (), pl = plist;
42
43       for (MPlist p = this; p.next != null; p = p.next)
44         pl = pl.Add (p.Key, p.Val);
45       return plist;
46     }
47
48     public override string ToString ()
49     {
50         string str = "";
51
52         for (MPlist p = this; ! p.IsEmpty; p = p.next)
53           {
54             str += (p == this ? "(" : " ") + p.Key + ":" + p.Val;
55           }
56         return str + ")";
57     }
58
59     private MPlist find (MSymbol key)
60     {
61       MPlist p;
62
63       for (p = this; ! p.IsEmpty; p = p.next)
64         if (p.Key == key)
65           break;
66       return p;
67     }
68
69     public MPlist Find (MSymbol key)
70     {
71       MPlist p = find (key);
72
73       return (p.IsEmpty ? null : p);
74     }
75
76     public object Get (MSymbol key)
77     {
78       return find (key).Val;
79     }
80
81     public MPlist Set (MSymbol key, object val)
82     {
83       if (IsEmpty)
84         Push (key, val);
85       else
86         Val = val;
87       return this;
88     }
89
90     public MPlist Put (MSymbol key, object val)
91     {
92       return find (key).Set (key, val);
93     }
94
95     public MPlist Push (MSymbol key, object val)
96     {
97       MPlist p = new MPlist (Key, Val);
98
99       p.next = this.next;
100       Key = key;
101       Val = val;
102       next = p;
103       return this;
104     }
105
106     public object Pop ()
107     {
108       if (IsEmpty)
109         return null;
110
111       object val = Val;
112
113       Key = next.Key;
114       Val = next.Val;
115       next = next.next;
116       return val;
117     }
118
119     public MPlist Add (MSymbol key, object val)
120     {
121       MPlist p;
122
123       for (p = this; ! p.IsEmpty; p = p.next);
124       return p.Push (key, val);
125     }
126
127     // Implement IEnumerable interface.
128     //   foreach (MPlist p in plist) { ... }
129
130     public virtual IEnumerator GetEnumerator ()
131     {
132       return new Enumerator (this);
133     }
134
135     private class Enumerator : IEnumerator
136     {
137       private MPlist plist;
138       private MPlist current;
139
140       internal Enumerator (MPlist plist)
141         {
142           this.plist = plist;
143         }
144
145       public object Current
146       {
147         get {
148           if (current == null || current.IsEmpty)
149             throw new InvalidOperationException ();
150           return current;
151         }
152       }
153
154       public void Reset ()
155       {
156         current = null;
157       }
158
159       public bool MoveNext ()
160       {
161         if (current == null)
162           current = plist;
163         else
164           current = current.next;
165         return (! current.IsEmpty);
166       }
167     }
168   }
169 }