Applied patch from Jan Limpens 'ReflectionBasedDictionaryAdapter needs to check if...
[castle.git] / Core / Castle.Core / Internal / LinkedList.cs
blob1dfe90184828467177b69a242412e43bf1bb4eef
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 #if !SILVERLIGHT
21 [Serializable]
22 #endif
23 public class LinkedList : IList
25 private LinkNode internalhead;
26 private LinkNode internaltail;
27 private int internalcount;
29 public LinkedList()
33 public object Head
35 get
37 if (internalhead == null) return null;
38 return internalhead.Value;
42 public virtual void AddFirst(object value)
44 if (internalhead == null)
46 internalhead = new LinkNode(value);
48 else
50 internalhead = new LinkNode(value, internalhead, null);
53 internalcount++;
56 public virtual int AddLast(object value)
58 if (internalhead == null)
60 internalhead = new LinkNode(value);
62 else
64 LinkNode p, q;
65 for(p = internalhead; (q = p.Next) != null; p = q) ;
66 p.Next = new LinkNode(value, null, p);
69 return internalcount++;
72 public virtual int Add(object value)
74 if (internalhead == null)
76 internalhead = new LinkNode(value);
78 internaltail = internalhead;
80 else
82 // Added this code because internaltail seems to be null in come cases
83 if (internaltail == null)
85 internaltail = internalhead;
87 while(internaltail.Next != null)
88 internaltail = internaltail.Next;
91 internaltail.Next = new LinkNode(value, null, internaltail);
93 internaltail = internaltail.Next;
96 return internalcount++;
99 public bool Contains(object value)
101 if (value == null) throw new ArgumentNullException("value");
103 foreach(object item in this)
105 if (value.Equals(item))
107 return true;
111 return false;
114 public void Clear()
116 internalhead = internaltail = null;
117 internalcount = 0;
120 public virtual bool Replace(object old, object value)
122 LinkNode node = internalhead;
124 while(node != null)
126 if (node.Value.Equals(old))
128 node.Value = value;
129 return true;
132 node = node.Next;
135 return false;
138 public int IndexOf(object value)
140 if (value == null) throw new ArgumentNullException("value");
142 int index = -1;
144 foreach(object item in this)
146 index++;
148 if (value.Equals(item))
150 return index;
154 return -1;
157 public virtual void Insert(int index, object value)
159 if (index == 0)
161 AddFirst(value);
163 else if (index == internalcount)
165 AddLast(value);
167 else
169 LinkNode insert = GetNode(index);
170 LinkNode node = new LinkNode(value, insert, insert.Previous);
171 insert.Previous.Next = node;
172 insert.Previous = node;
173 internalcount++;
177 /// <summary>
178 /// Returns the node at the specified index.
179 /// </summary>
180 /// <param name="index">The lookup index.</param>
181 /// <returns>The node at the specified index.</returns>
182 /// <exception cref="System.ArgumentOutOfRangeException">
183 /// If the specified <paramref name="index"/> is greater than the
184 /// number of objects within the list.
185 /// </exception>
186 private LinkNode GetNode(int index)
188 ValidateIndex(index);
189 LinkNode node = internalhead;
190 for(int i = 0; i < index; i++)
192 node = node.Next;
194 return node;
197 /// <summary>
198 /// Validates the specified index.
199 /// </summary>
200 /// <param name="index">The lookup index.</param>
201 /// <exception cref="System.ArgumentOutOfRangeException">
202 /// If the index is invalid.
203 /// </exception>
204 private void ValidateIndex(int index)
206 if (index < 0 || index >= internalcount)
208 throw new ArgumentOutOfRangeException("index");
212 public virtual void Remove(object value)
214 if (internalhead != null)
216 if (internalhead.Value.Equals(value))
218 if (internalhead == internaltail) internaltail = null;
220 internalhead = internalhead.Next;
222 internalcount--;
224 else if (internaltail.Value.Equals(value))
226 internaltail.Previous.Next = null;
227 internaltail = internaltail.Previous;
229 internalcount--;
231 else
233 LinkNode node = internalhead.Next;
235 while(node != null)
237 if (node.Value.Equals(value))
239 node.Previous.Next = node.Next;
240 node.Next.Previous = node.Previous;
241 internalcount--;
242 break;
245 node = node.Next;
251 public virtual void RemoveAt(int index)
253 throw new NotImplementedException();
256 public bool IsReadOnly
258 get { return false; }
261 public bool IsFixedSize
263 get { return false; }
266 public object this[int index]
268 get { throw new NotImplementedException(); }
269 set { throw new NotImplementedException(); }
272 public int Count
274 get { return internalcount; }
277 public Array ToArray(Type type)
279 Array array = Array.CreateInstance(type, Count);
281 int index = 0;
283 foreach(Object value in this)
285 array.SetValue(value, index++);
288 return array;
291 #region IEnumerable Members
293 public IEnumerator GetEnumerator()
295 return new LinkedListEnumerator(internalhead);
298 #endregion
300 public void CopyTo(Array array, int index)
302 throw new NotImplementedException();
305 public object SyncRoot
307 get { return this; }
310 public bool IsSynchronized
312 get { return false; }
316 #if !SILVERLIGHT
317 [Serializable]
318 #endif
319 internal class LinkNode
321 private object _value;
322 private LinkNode _next;
323 private LinkNode _prev;
325 public LinkNode(object value) : this(value, null, null)
329 public LinkNode(object value, LinkNode next, LinkNode prev)
331 _value = value;
332 _next = next;
333 _prev = prev;
336 public LinkNode Next
338 get { return _next; }
339 set { _next = value; }
342 public LinkNode Previous
344 get { return _prev; }
345 set { _prev = value; }
348 public object Value
350 get { return _value; }
351 set { _value = value; }
355 internal class LinkedListEnumerator : IEnumerator
357 private LinkNode internalhead;
358 private LinkNode _current;
359 private bool _isFirst;
361 public LinkedListEnumerator(LinkNode node)
363 internalhead = node;
364 Reset();
367 public void Reset()
369 _current = internalhead;
370 _isFirst = true;
373 public object Current
375 get { return _current.Value; }
378 public bool MoveNext()
380 if (_current == null) return false;
382 if (!_isFirst)
384 _current = _current.Next;
386 else
388 _isFirst = false;
391 return _current != null;