More working tests.
[castle.git] / Core / Castle.Core / Internal / LinkedList.cs
bloba24c10dcd73b1c81107d4f9e05866878075133d3
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Core.Internal
17 using System;
18 using System.Collections;
20 [Serializable]
21 public class LinkedList : IList
23 private LinkNode internalhead;
24 private LinkNode internaltail;
25 private int internalcount;
27 public LinkedList()
31 public object Head
33 get
35 if (internalhead == null) return null;
36 return internalhead.Value;
40 public virtual void AddFirst(object value)
42 if (internalhead == null)
44 internalhead = new LinkNode(value);
46 else
48 internalhead = new LinkNode(value, internalhead, null);
51 internalcount++;
54 public virtual int AddLast(object value)
56 if (internalhead == null)
58 internalhead = new LinkNode(value);
60 else
62 LinkNode p, q;
63 for(p = internalhead; (q = p.Next) != null; p = q) ;
64 p.Next = new LinkNode(value, null, p);
67 return internalcount++;
70 public virtual int Add(object value)
72 if (internalhead == null)
74 internalhead = new LinkNode(value);
76 internaltail = internalhead;
78 else
80 // Added this code because internaltail seems to be null in come cases
81 if (internaltail == null)
83 internaltail = internalhead;
85 while(internaltail.Next != null)
86 internaltail = internaltail.Next;
89 internaltail.Next = new LinkNode(value, null, internaltail);
91 internaltail = internaltail.Next;
94 return internalcount++;
97 public bool Contains(object value)
99 if (value == null) throw new ArgumentNullException("value");
101 foreach(object item in this)
103 if (value.Equals(item))
105 return true;
109 return false;
112 public void Clear()
114 internalhead = internaltail = null;
115 internalcount = 0;
118 public virtual bool Replace(object old, object value)
120 LinkNode node = internalhead;
122 while(node != null)
124 if (node.Value.Equals(old))
126 node.Value = value;
127 return true;
130 node = node.Next;
133 return false;
136 public int IndexOf(object value)
138 if (value == null) throw new ArgumentNullException("value");
140 int index = -1;
142 foreach(object item in this)
144 index++;
146 if (value.Equals(item))
148 return index;
152 return -1;
155 public virtual void Insert(int index, object value)
157 if (index == 0)
159 AddFirst(value);
161 else if (index == internalcount)
163 AddLast(value);
165 else
167 LinkNode insert = GetNode(index);
168 LinkNode node = new LinkNode(value, insert, insert.Previous);
169 insert.Previous.Next = node;
170 insert.Previous = node;
171 internalcount++;
175 /// <summary>
176 /// Returns the node at the specified index.
177 /// </summary>
178 /// <param name="index">The lookup index.</param>
179 /// <returns>The node at the specified index.</returns>
180 /// <exception cref="System.ArgumentOutOfRangeException">
181 /// If the specified <paramref name="index"/> is greater than the
182 /// number of objects within the list.
183 /// </exception>
184 private LinkNode GetNode(int index)
186 ValidateIndex(index);
187 LinkNode node = internalhead;
188 for(int i = 0; i < index; i++)
190 node = node.Next;
192 return node;
195 /// <summary>
196 /// Validates the specified index.
197 /// </summary>
198 /// <param name="index">The lookup index.</param>
199 /// <exception cref="System.ArgumentOutOfRangeException">
200 /// If the index is invalid.
201 /// </exception>
202 private void ValidateIndex(int index)
204 if (index < 0 || index >= internalcount)
206 throw new ArgumentOutOfRangeException("index");
210 public virtual void Remove(object value)
212 if (internalhead != null)
214 if (internalhead.Value.Equals(value))
216 if (internalhead == internaltail) internaltail = null;
218 internalhead = internalhead.Next;
220 internalcount--;
222 else if (internaltail.Value.Equals(value))
224 internaltail.Previous.Next = null;
225 internaltail = internaltail.Previous;
227 internalcount--;
229 else
231 LinkNode node = internalhead.Next;
233 while(node != null)
235 if (node.Value.Equals(value))
237 node.Previous.Next = node.Next;
238 node.Next.Previous = node.Previous;
239 internalcount--;
240 break;
243 node = node.Next;
249 public virtual void RemoveAt(int index)
251 throw new NotImplementedException();
254 public bool IsReadOnly
256 get { return false; }
259 public bool IsFixedSize
261 get { return false; }
264 public object this[int index]
266 get { throw new NotImplementedException(); }
267 set { throw new NotImplementedException(); }
270 public int Count
272 get { return internalcount; }
275 public Array ToArray(Type type)
277 Array array = Array.CreateInstance(type, Count);
279 int index = 0;
281 foreach(Object value in this)
283 array.SetValue(value, index++);
286 return array;
289 #region IEnumerable Members
291 public IEnumerator GetEnumerator()
293 return new LinkedListEnumerator(internalhead);
296 #endregion
298 public void CopyTo(Array array, int index)
300 throw new NotImplementedException();
303 public object SyncRoot
305 get { return this; }
308 public bool IsSynchronized
310 get { return false; }
314 [Serializable]
315 internal class LinkNode
317 private object _value;
318 private LinkNode _next;
319 private LinkNode _prev;
321 public LinkNode(object value) : this(value, null, null)
325 public LinkNode(object value, LinkNode next, LinkNode prev)
327 _value = value;
328 _next = next;
329 _prev = prev;
332 public LinkNode Next
334 get { return _next; }
335 set { _next = value; }
338 public LinkNode Previous
340 get { return _prev; }
341 set { _prev = value; }
344 public object Value
346 get { return _value; }
347 set { _value = value; }
351 internal class LinkedListEnumerator : IEnumerator
353 private LinkNode internalhead;
354 private LinkNode _current;
355 private bool _isFirst;
357 public LinkedListEnumerator(LinkNode node)
359 internalhead = node;
360 Reset();
363 public void Reset()
365 _current = internalhead;
366 _isFirst = true;
369 public object Current
371 get { return _current.Value; }
374 public bool MoveNext()
376 if (_current == null) return false;
378 if (!_isFirst)
380 _current = _current.Next;
382 else
384 _isFirst = false;
387 return _current != null;