1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
23 public class LinkedList
: IList
25 private LinkNode internalhead
;
26 private LinkNode internaltail
;
27 private int internalcount
;
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);
50 internalhead
= new LinkNode(value, internalhead
, null);
56 public virtual int AddLast(object value)
58 if (internalhead
== null)
60 internalhead
= new LinkNode(value);
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
;
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
))
116 internalhead
= internaltail
= null;
120 public virtual bool Replace(object old
, object value)
122 LinkNode node
= internalhead
;
126 if (node
.Value
.Equals(old
))
138 public int IndexOf(object value)
140 if (value == null) throw new ArgumentNullException("value");
144 foreach(object item
in this)
148 if (value.Equals(item
))
157 public virtual void Insert(int index
, object value)
163 else if (index
== internalcount
)
169 LinkNode insert
= GetNode(index
);
170 LinkNode node
= new LinkNode(value, insert
, insert
.Previous
);
171 insert
.Previous
.Next
= node
;
172 insert
.Previous
= node
;
178 /// Returns the node at the specified index.
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.
186 private LinkNode
GetNode(int index
)
188 ValidateIndex(index
);
189 LinkNode node
= internalhead
;
190 for(int i
= 0; i
< index
; i
++)
198 /// Validates the specified index.
200 /// <param name="index">The lookup index.</param>
201 /// <exception cref="System.ArgumentOutOfRangeException">
202 /// If the index is invalid.
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
;
224 else if (internaltail
.Value
.Equals(value))
226 internaltail
.Previous
.Next
= null;
227 internaltail
= internaltail
.Previous
;
233 LinkNode node
= internalhead
.Next
;
237 if (node
.Value
.Equals(value))
239 node
.Previous
.Next
= node
.Next
;
240 node
.Next
.Previous
= node
.Previous
;
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(); }
274 get { return internalcount; }
277 public Array
ToArray(Type type
)
279 Array array
= Array
.CreateInstance(type
, Count
);
283 foreach(Object
value in this)
285 array
.SetValue(value, index
++);
291 #region IEnumerable Members
293 public IEnumerator
GetEnumerator()
295 return new LinkedListEnumerator(internalhead
);
300 public void CopyTo(Array array
, int index
)
302 throw new NotImplementedException();
305 public object SyncRoot
310 public bool IsSynchronized
312 get { return false; }
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
)
338 get { return _next; }
339 set { _next = value; }
342 public LinkNode Previous
344 get { return _prev; }
345 set { _prev = 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
)
369 _current
= internalhead
;
373 public object Current
375 get { return _current.Value; }
378 public bool MoveNext()
380 if (_current
== null) return false;
384 _current
= _current
.Next
;
391 return _current
!= null;