5 // Chris J Breisch (cjbreisch@altavista.net)
7 // (C) 2002 Chris J Breisch
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Runtime.InteropServices;
34 using System.Collections;
35 using System.ComponentModel;
36 using Microsoft.VisualBasic.CompilerServices;
39 namespace Microsoft.VisualBasic {
40 sealed public class Collection : ICollection, IList {
43 // Collection : The BASIC Collection Object
49 private Hashtable m_Hashtable = new Hashtable();
50 private ArrayList m_HashIndexers = new ArrayList();
51 internal bool Modified = false;
53 private class ColEnumerator: IEnumerator
56 // ColEnumerator : This internal class is used
57 // for enumerating through our Collection
64 private Collection Col;
67 public ColEnumerator(Collection coll)
78 // FIXME : spec says throw exception, MS doesn't
79 // throw new InvalidOperationException();
84 public bool MoveNext()
88 // FIXME : spec says throw exception, MS doesn't
89 // throw new InvalidOperationException();
99 return Index <= Col.Count;
102 public object Current {
105 // FIXME : spec says throw InvalidOperation,
106 // but MS throws IndexOutOfRange
107 throw new IndexOutOfRangeException();
108 // throw new InvalidOperationException();
116 // The current property on the IEnumerator interface:
117 object IEnumerator.Current {
125 System.Boolean IList.IsReadOnly {
129 System.Boolean ICollection.IsSynchronized {
130 get {return m_Hashtable.IsSynchronized;}
133 System.Object ICollection.SyncRoot {
134 get {return m_Hashtable.SyncRoot;}
137 System.Boolean IList.IsFixedSize {
141 public System.Int32 Count {
142 get {return m_HashIndexers.Count;}
146 [System.Runtime.CompilerServices.IndexerName("Item")]
147 public System.Object this [System.Int32 Index] {
150 // Collections are 1-based
151 return m_Hashtable[m_HashIndexers[Index-1]];
154 throw new IndexOutOfRangeException();
157 set {throw new NotImplementedException();}
160 [System.Runtime.CompilerServices.IndexerName("Item")]
161 public System.Object this [System.Object Index]
164 if (Index is string) {
165 if (m_HashIndexers.IndexOf(Index) < 0) {
166 // throw new IndexOutOfRangeException();
167 // FIXME : Spec Says IndexOutOfRange...MS throws Argument
168 throw new ArgumentException();
170 return m_Hashtable[Index];
173 throw new ArgumentException();
179 System.Int32 IList.IndexOf (System.Object value)
185 LastPos = m_HashIndexers.IndexOf(value.GetHashCode(), LastPos);
188 } else if (m_Hashtable[m_HashIndexers[LastPos]] == value) {
195 System.Boolean IList.Contains (System.Object value)
197 return m_Hashtable.ContainsValue(value);
203 m_HashIndexers.Clear();
206 public void Remove (System.String Key)
211 throw new ArgumentNullException();
214 Index = m_HashIndexers.IndexOf(Key) + 1;
218 throw new ArgumentException();
222 public void Remove (System.Int32 Index)
225 // Collections are 1-based
226 m_Hashtable.Remove(m_HashIndexers[Index-1]);
227 m_HashIndexers.RemoveAt(Index-1);
231 throw new IndexOutOfRangeException();
235 void IList.Remove (System.Object value)
238 throw new ArgumentNullException();
240 if (!(value is string)) {
241 throw new ArgumentException();
243 Remove((string)value);
246 void IList.RemoveAt (System.Int32 index)
251 void IList.Insert (System.Int32 index, System.Object value)
253 Insert(index, value, value.GetHashCode().ToString());
256 void Insert(System.Int32 index, System.Object value, string Key)
258 m_HashIndexers.Insert(index -1, Key);
259 m_Hashtable.Add(Key, value);
263 System.Int32 IList.Add (System.Object Item)
265 return Add(Item, Item.GetHashCode().ToString());
268 System.Int32 Add(System.Object Item, string Key)
270 m_Hashtable.Add(Key, Item);
273 return m_HashIndexers.Add(Key);
276 private int GetIndexPosition(System.Object Item)
278 int Position = int.MinValue;
280 if (Item is string) {
281 Position = m_HashIndexers.IndexOf(Item) + 1;
283 else if (Item is int) {
284 Position = Convert.ToInt32(Item);
287 throw new InvalidCastException();
290 throw new ArgumentException();
293 //Position must be from 1 to value of collections Count
294 if (Position > m_HashIndexers.Count) {
295 throw new ArgumentOutOfRangeException();
301 public void Add (System.Object Item,
302 [Optional, __DefaultArgumentValue(null)] String Key,
303 [Optional, __DefaultArgumentValue(null)] System.Object Before,
304 [Optional, __DefaultArgumentValue(null)] System.Object After)
306 int Position = int.MinValue;
308 // check for valid args
309 if (Before != null && After != null) {
310 throw new ArgumentException();
312 if (Key != null && m_HashIndexers.IndexOf(Key) != -1) {
313 throw new ArgumentException();
315 if (Before != null) {
316 // Looks like its an implementation bug in .NET
317 // Not very satisfied with the fix, but did it
318 // just to bring the similar behaviour on mono
321 Position = Convert.ToInt32(Before);
322 if (Position != (m_HashIndexers.Count + 1))
323 Position = GetIndexPosition(Before);
326 Position = GetIndexPosition(Before);
329 Position = GetIndexPosition(After) + 1;
332 Key = (Item.GetHashCode() + m_HashIndexers.Count).ToString();
335 if (Position > (m_HashIndexers.Count+1) || Position == int.MinValue) {
339 Insert(Position, Item, Key);
343 void ICollection.CopyTo (System.Array array, System.Int32 index)
345 System.Array NewArray =
346 Array.CreateInstance(typeof(System.Object),
347 m_HashIndexers.Count - index);
349 // Collections are 1-based
350 for (int i = index -1; i < m_HashIndexers.Count; i++) {
351 NewArray.SetValue(m_Hashtable[m_HashIndexers[i]], i - index);
355 public IEnumerator GetEnumerator ()
357 return new ColEnumerator(this);