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
;
21 public class LinkedList
: IList
23 private LinkNode internalhead
;
24 private LinkNode internaltail
;
25 private int internalcount
;
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);
48 internalhead
= new LinkNode(value, internalhead
, null);
54 public virtual int AddLast(object value)
56 if (internalhead
== null)
58 internalhead
= new LinkNode(value);
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
;
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
))
114 internalhead
= internaltail
= null;
118 public virtual bool Replace(object old
, object value)
120 LinkNode node
= internalhead
;
124 if (node
.Value
.Equals(old
))
136 public int IndexOf(object value)
138 if (value == null) throw new ArgumentNullException("value");
142 foreach(object item
in this)
146 if (value.Equals(item
))
155 public virtual void Insert(int index
, object value)
161 else if (index
== internalcount
)
167 LinkNode insert
= GetNode(index
);
168 LinkNode node
= new LinkNode(value, insert
, insert
.Previous
);
169 insert
.Previous
.Next
= node
;
170 insert
.Previous
= node
;
176 /// Returns the node at the specified index.
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.
184 private LinkNode
GetNode(int index
)
186 ValidateIndex(index
);
187 LinkNode node
= internalhead
;
188 for(int i
= 0; i
< index
; i
++)
196 /// Validates the specified index.
198 /// <param name="index">The lookup index.</param>
199 /// <exception cref="System.ArgumentOutOfRangeException">
200 /// If the index is invalid.
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
;
222 else if (internaltail
.Value
.Equals(value))
224 internaltail
.Previous
.Next
= null;
225 internaltail
= internaltail
.Previous
;
231 LinkNode node
= internalhead
.Next
;
235 if (node
.Value
.Equals(value))
237 node
.Previous
.Next
= node
.Next
;
238 node
.Next
.Previous
= node
.Previous
;
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(); }
272 get { return internalcount; }
275 public Array
ToArray(Type type
)
277 Array array
= Array
.CreateInstance(type
, Count
);
281 foreach(Object
value in this)
283 array
.SetValue(value, index
++);
289 #region IEnumerable Members
291 public IEnumerator
GetEnumerator()
293 return new LinkedListEnumerator(internalhead
);
298 public void CopyTo(Array array
, int index
)
300 throw new NotImplementedException();
303 public object SyncRoot
308 public bool IsSynchronized
310 get { return false; }
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
)
334 get { return _next; }
335 set { _next = value; }
338 public LinkNode Previous
340 get { return _prev; }
341 set { _prev = 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
)
365 _current
= internalhead
;
369 public object Current
371 get { return _current.Value; }
374 public bool MoveNext()
376 if (_current
== null) return false;
380 _current
= _current
.Next
;
387 return _current
!= null;