2002-09-24 Nick Drochak <ndrochak@gol.com>
[mono.git] / mcs / class / corlib / System.Collections / ArrayList.cs
1 //\r
2 // System.Collections.ArrayList\r
3 //\r
4 // Author:\r
5 //    Vladimir Vukicevic (vladimir@pobox.com)\r
6 //    Duncan Mak (duncan@ximian.com)\r
7 //\r
8 // (C) 2001 Vladimir Vukicevic\r
9 // (C) 2002 Ximian, Inc.\r
10 //\r
11 \r
12 using System;\r
13 \r
14 namespace System.Collections {\r
15 \r
16         [MonoTODO ("add versioning, changing the arraylist should invalidate all enumerators")]\r
17         [Serializable]\r
18         public class ArrayList : IList, ICollection, IEnumerable, ICloneable {\r
19 \r
20                 // Keep these three fields in sync with mono-reflection.h.\r
21                 private int count = 0;\r
22                 private int capacity = defaultCapacity;\r
23                 private object[] dataArray;\r
24                 \r
25                 // constructors\r
26                 public ArrayList () {\r
27                         dataArray = new object[capacity];\r
28                 }\r
29 \r
30                 public ArrayList (ICollection c) {\r
31                         if (null == c)\r
32                                 throw new ArgumentNullException();\r
33 \r
34                         //Emulate MS.NET behavior. Throw RankException when passed a\r
35                         // multi-dimensional Array.\r
36                         Array arr = c as Array;\r
37                         if (null != arr && arr.Rank > 1)\r
38                                 throw new RankException ();\r
39 \r
40                         this.capacity = (c.Count == 0) ? defaultCapacity : c.Count;\r
41                         dataArray = new object [capacity];\r
42                         foreach (object o in c) \r
43                                 Add (o);\r
44                 }\r
45 \r
46                 public ArrayList (int capacity) {\r
47                         if (capacity < 0)\r
48                                 throw new ArgumentOutOfRangeException ("capacity", capacity, "Value must be greater than or equal to zero.");\r
49 \r
50                         if (capacity > 0)\r
51                                 this.capacity = capacity;\r
52                         // else if capacity == 0 then use defaultCapacity\r
53 \r
54                         dataArray = new object[this.capacity];\r
55                 }\r
56 \r
57                 private ArrayList (object[] dataArray, int count, int capacity,\r
58                                    bool fixedSize, bool readOnly, bool synchronized)\r
59                 {\r
60                         this.dataArray = new object [capacity];\r
61                         dataArray.CopyTo (this.dataArray, 0);\r
62                         this.count = count;\r
63                         this.capacity = capacity;\r
64                         this.fixedSize = fixedSize;\r
65                         this.readOnly = readOnly;\r
66                         this.synchronized = synchronized;\r
67                 }\r
68 \r
69                 public static ArrayList ReadOnly (ArrayList list)\r
70                 {\r
71                         if (list == null)\r
72                                 throw new ArgumentNullException ();\r
73                         return new ArrayList (list.ToArray (), list.Count, list.Capacity,\r
74                                               list.IsFixedSize, true, list.IsSynchronized);\r
75                 }\r
76 \r
77                 public static IList ReadOnly (IList list)\r
78                 {\r
79                         if (list == null)\r
80                                 throw new ArgumentNullException ();\r
81 \r
82                         ArrayList al = new ArrayList ();\r
83 \r
84                         foreach (object o in list)\r
85                                 al.Add (o);\r
86 \r
87                         return (IList) ArrayList.ReadOnly (al);\r
88                 }\r
89 \r
90                 public static ArrayList Synchronized (ArrayList list)\r
91                 {\r
92                         if (list == null)\r
93                                 throw new ArgumentNullException ();\r
94 \r
95                         return new ArrayList (list.ToArray (), list.Count, list.Capacity,\r
96                                               list.IsFixedSize, list.IsReadOnly, true);\r
97                 }\r
98 \r
99                 public static IList Synchronized (IList list)\r
100                 {\r
101                         if (list == null)\r
102                                 throw new ArgumentNullException ();\r
103 \r
104                         ArrayList al = new ArrayList ();\r
105 \r
106                         foreach (object o in list)\r
107                                 al.Add (o);\r
108 \r
109                         return (IList) ArrayList.Synchronized (al);\r
110                 }\r
111 \r
112                 public static ArrayList FixedSize (ArrayList list)\r
113                 {\r
114                         if (list == null)\r
115                                 throw new ArgumentNullException ();\r
116 \r
117                         return new ArrayList (list.ToArray (), list.Count, list.Capacity,\r
118                                               true, list.IsReadOnly, list.IsSynchronized);\r
119                 }\r
120 \r
121                 public static IList FixedSize (IList list)\r
122                 {\r
123                         if (list == null)\r
124                                 throw new ArgumentNullException ();\r
125 \r
126                         ArrayList al = new ArrayList ();\r
127 \r
128                         foreach (object o in list)\r
129                                 al.Add (o);\r
130 \r
131                         return (IList) ArrayList.FixedSize (al);                        \r
132                 }\r
133 \r
134                 public static ArrayList Repeat (object value, int count)\r
135                 {\r
136                         ArrayList al = new ArrayList (count);\r
137                         for (int i = 0; i < count; i++) {\r
138                                 al.dataArray[i] = value;\r
139                         }\r
140                         al.count = count;\r
141 \r
142                         return al;\r
143                 }\r
144 \r
145                 [Serializable]\r
146                 private class ListWrapper : ArrayList\r
147                 {\r
148                         IList list;\r
149 \r
150                         public ListWrapper (IList list)\r
151                         {\r
152                                 if (null == list)\r
153                                         throw new ArgumentNullException();\r
154 \r
155                                 this.list = list;\r
156                                 count = ((ICollection) list).Count;\r
157                         }\r
158                         \r
159                         // ArrayList\r
160                         [MonoTODO]\r
161                         public override int Capacity {\r
162                                 get { return list.Count; }\r
163                                 set { throw new NotSupportedException (); }\r
164                         }\r
165 \r
166                         [MonoTODO]\r
167                         public override void AddRange (ICollection collection)\r
168                         {\r
169                                 if (collection == null)\r
170                                         throw new ArgumentNullException ("colllection");\r
171                                 if (IsFixedSize || IsReadOnly)\r
172                                         throw new NotSupportedException ();\r
173                         }\r
174 \r
175                         [MonoTODO]\r
176                         public override int BinarySearch (object value)\r
177                         {\r
178                                 throw new NotImplementedException ();\r
179                         }\r
180 \r
181                         [MonoTODO]\r
182                         public override int BinarySearch (object value, IComparer comparer)\r
183                         {\r
184                                 throw new NotImplementedException ();\r
185                         }\r
186 \r
187                         [MonoTODO]\r
188                         public override int BinarySearch (int index, int count, object value,\r
189                                                           IComparer comparer)\r
190                         {\r
191                                 throw new NotImplementedException ();\r
192                         }\r
193 \r
194                         public override void CopyTo (Array array)\r
195                         {\r
196                                 if (null == array)\r
197                                         throw new ArgumentNullException("array");\r
198                                 if (array.Rank > 1)\r
199                                         throw new ArgumentException("array cannot be multidimensional");\r
200 \r
201                                 CopyTo (array, 0);\r
202                         }\r
203 \r
204                         [MonoTODO]\r
205                         public override void CopyTo (int index, Array array,\r
206                                                      int arrayIndex, int count)\r
207                         {\r
208                                 if (array == null)\r
209                                         throw new ArgumentNullException ();\r
210                                 if (index < 0 || arrayIndex < 0 || count < 0)\r
211                                         throw new ArgumentOutOfRangeException ();\r
212                                 if (array.Rank > 1 || index >= Count || Count > (array.Length - arrayIndex))\r
213                                         throw new ArgumentException ();\r
214                                 // FIXME: handle casting error here\r
215                         }\r
216 \r
217                         public override ArrayList GetRange (int index, int count)\r
218                         {\r
219                                 if (index < 0 || count < 0)\r
220                                         throw new ArgumentOutOfRangeException ();\r
221                                 if (Count < (index + count))\r
222                                         throw new ArgumentException ();\r
223                                 \r
224                                 ArrayList result = new ArrayList (count);\r
225 \r
226                                 for (int i = 0; i < count; i++)\r
227                                         result.Add (list [i]);\r
228 \r
229                                 return result;\r
230                         }\r
231 \r
232                         [MonoTODO]\r
233                         public override void InsertRange (int index, ICollection col)\r
234                         {\r
235                                 if (col == null)\r
236                                         throw new ArgumentNullException ();\r
237                                 if (index < 0 || index > Count)\r
238                                         throw new ArgumentOutOfRangeException ();\r
239                                 if (IsReadOnly || IsFixedSize)\r
240                                         throw new NotSupportedException ();\r
241 \r
242                                 if (index == Count) {\r
243                                         foreach (object element in col)\r
244                                                 list.Add (element);\r
245 \r
246                                 } //else if ((index + count) < Count) {\r
247 //                                      for (int i = index; i < (index + count); i++)\r
248 //                                              list [i] = col [i];\r
249 \r
250 //                              } else {\r
251 //                                      int added = Count - (index + count);\r
252 //                                      for (int i = index; i < Count; i++)\r
253 //                                              list [i] = col [i];\r
254 //                                      for (int i = 0; i < added; i++)\r
255 //                                              list.Add (col [Count +i]);\r
256 //                              }\r
257                         }\r
258 \r
259                         public override int LastIndexOf (object value)\r
260                         {\r
261                                 return LastIndexOf (value, Count, 0);\r
262                         }\r
263 \r
264                         public override int LastIndexOf (object value, int startIndex)\r
265                         {\r
266                                 return LastIndexOf (value, startIndex, 0);\r
267                         }\r
268 \r
269                         public override int LastIndexOf (object value, int startIndex, int count)\r
270                         {\r
271                                 if (null == value){\r
272                                         return -1;\r
273                                 }\r
274 \r
275                                 if (startIndex > Count || count < 0 || (startIndex + count > Count))\r
276                                         throw new ArgumentOutOfRangeException ();\r
277                                 \r
278                                 int length = startIndex - count + 1;\r
279 \r
280                                 for (int i = startIndex; i >= length; i--)\r
281                                         if (list [i] == value)\r
282                                                 return i;\r
283                                 return -1;\r
284                         }\r
285 \r
286                         public override void RemoveRange (int index, int count)\r
287                         {\r
288                                 if ((index < 0) || (count < 0))\r
289                                         throw new ArgumentOutOfRangeException ();\r
290                                 if ((index > Count) || (index + count) > Count)\r
291                                         throw new ArgumentException ();\r
292                                 if (IsReadOnly || IsFixedSize)\r
293                                         throw new NotSupportedException ();\r
294 \r
295                                 for (int i  = 0; i < count; i++)\r
296                                         list.RemoveAt (index);\r
297                         }\r
298 \r
299                         public override void Reverse ()\r
300                         {\r
301                                 Reverse (0, Count);\r
302                         }\r
303 \r
304                         public override void Reverse (int index, int count)\r
305                         {\r
306                                 if ((index < 0) || (count < 0))\r
307                                         throw new ArgumentOutOfRangeException ();\r
308                                 if ((index > Count) || (index + count) > Count)\r
309                                         throw new ArgumentException ();\r
310                                 if (IsReadOnly)\r
311                                         throw new NotSupportedException ();\r
312 \r
313                                 object tmp = null;\r
314 \r
315                                 for (int i = index; i < count; i++) {\r
316                                         tmp = list [i];\r
317                                         list [i] = list [count - i];\r
318                                         list [count - i] = tmp;\r
319                                 }\r
320                         }\r
321 \r
322                         public override void SetRange (int index, ICollection col)\r
323                         {\r
324                                 if (index < 0 || (index + col.Count) > Count)\r
325                                         throw new ArgumentOutOfRangeException ();\r
326                                 if (col == null)\r
327                                         throw new ArgumentNullException ();\r
328                                 if (IsReadOnly)\r
329                                         throw new NotSupportedException ();\r
330 \r
331                                 for (int i = index; i < col.Count; i++)\r
332                                         foreach (object o in col)\r
333                                                 list [i] = o;\r
334                         }\r
335 \r
336                         [MonoTODO]\r
337                         public override void Sort ()\r
338                         {\r
339                         }\r
340 \r
341                         [MonoTODO]\r
342                         public override void Sort (IComparer comparer)\r
343                         {\r
344                         }\r
345 \r
346                         [MonoTODO]\r
347                         public override void Sort (int index, int count, IComparer comparer)\r
348                         {\r
349                         }\r
350 \r
351                         public override object [] ToArray ()\r
352                         {\r
353                                 return (object []) ToArray (typeof (object));\r
354                         }\r
355 \r
356                         public override Array ToArray (Type type)\r
357                         {\r
358                                 int count = Count;\r
359                                 Array result = Array.CreateInstance (type, count);\r
360 \r
361                                 for (int i = 0; i < count; i++)\r
362                                         result.SetValue (list [i], i);\r
363 \r
364                                 return result;\r
365                         }\r
366 \r
367                         [MonoTODO]\r
368                         public override void TrimToSize ()\r
369                         {\r
370                         }\r
371 \r
372                         // IList\r
373                         public override bool IsFixedSize {\r
374                                 get { return list.IsFixedSize; }\r
375                         }\r
376 \r
377                         public override bool IsReadOnly {\r
378                                 get { return list.IsReadOnly; }\r
379                         }\r
380 \r
381                         public override object this [int index] {\r
382                                 get { return list [index]; }\r
383                                 set { list [index] = value; }\r
384                         }\r
385 \r
386                         public override int Add (object value)\r
387                         {\r
388                                 return list.Add (value);\r
389                         }\r
390 \r
391                         public override void Clear ()\r
392                         {\r
393                                 list.Clear ();\r
394                         }\r
395 \r
396                         public override bool Contains (object value)\r
397                         {\r
398                                 return list.Contains (value);\r
399                         }\r
400 \r
401                         public override int IndexOf (object value)\r
402                         {\r
403                                 return list.IndexOf (value);\r
404                         }\r
405 \r
406                         public override void Insert (int index, object value)\r
407                         {\r
408                                 list.Insert (index, value);\r
409                         }\r
410 \r
411                         public override void Remove (object value)\r
412                         {\r
413                                 list.Remove (value);\r
414                         }\r
415 \r
416                         public override void RemoveAt (int index)\r
417                         {\r
418                                 list.RemoveAt (index);\r
419                         }\r
420 \r
421                         // ICollection                  \r
422                         public override int Count {\r
423                                 get { return count; }\r
424                         }\r
425 \r
426                         public override bool IsSynchronized {\r
427                                 get { return ((ICollection) list).IsSynchronized; }\r
428                         }\r
429 \r
430                         public override object SyncRoot {\r
431                                 get { return ((ICollection) list).SyncRoot; }\r
432                         }\r
433 \r
434                         public override void CopyTo (Array array, int index)\r
435                         {\r
436                                 ((ICollection) list).CopyTo (array, index);\r
437                         }\r
438 \r
439                         // ICloneable\r
440                         public override object Clone ()\r
441                         {\r
442                                 return new ListWrapper (list);\r
443                         }\r
444 \r
445                         // IEnumerable\r
446                         public override IEnumerator GetEnumerator ()\r
447                         {\r
448                                 return ((IEnumerable) list).GetEnumerator ();\r
449                         }\r
450                 }\r
451 \r
452                 [MonoTODO]\r
453                 public static ArrayList Adapter (IList list)\r
454                 {\r
455                         return new ListWrapper (list);\r
456                 }\r
457 \r
458                 // properties\r
459 \r
460                 private bool fixedSize = false;\r
461                 private bool readOnly = false;\r
462                 private bool synchronized = false;\r
463 \r
464                 private long version = 0;\r
465                 private ArrayList source = null;\r
466 \r
467                 private const int defaultCapacity = 16;\r
468 \r
469                 private void copyDataArray (object[] outArray) {\r
470                         for (int i = 0; i < count; i++) {\r
471                                 outArray[i] = dataArray[i];\r
472                         }\r
473                 }\r
474 \r
475                 private void setSize (int newSize) {\r
476                         if (newSize == capacity) \r
477                                 return;\r
478                         \r
479                         capacity = (newSize == 0) ? defaultCapacity : newSize;\r
480 \r
481                         // note that this assumes that we've already sanity-checked\r
482                         // the new size\r
483                         object[] newDataArray = new object[newSize];\r
484                         copyDataArray (newDataArray);\r
485                         dataArray = newDataArray;\r
486                 }\r
487 \r
488                 // note that this DOES NOT update count\r
489                 private void shiftElements (int startIndex, int numshift) {\r
490                         if (numshift == 0) { \r
491                                 return;\r
492                         }\r
493 \r
494                         if (count + numshift > capacity) {\r
495                                 setSize (capacity * 2);\r
496                                 shiftElements (startIndex, numshift);\r
497                         } else {\r
498                                 if (numshift > 0) {\r
499                                         int numelts = count - startIndex;\r
500                                         for (int i = numelts-1; i >= 0; i--) {\r
501                                                 dataArray[startIndex + numshift + i] = dataArray[startIndex + i];\r
502                                         }\r
503 \r
504                                         for (int i = startIndex; i < startIndex + numshift; i++) {\r
505                                                 dataArray[i] = null;\r
506                                         }\r
507                                 } else {\r
508                                         int numelts = count - startIndex + numshift;\r
509                                         for (int i = 0; i < numelts; i++) {\r
510                                                 dataArray [i + startIndex] = dataArray [i + startIndex - numshift];\r
511                                         }\r
512                                         for (int i = count + numshift; i < count; i++) {\r
513                                                 dataArray[i] = null;\r
514                                         }\r
515                                 }\r
516                         }\r
517                 }\r
518 \r
519                 public virtual int Capacity {\r
520                         get {\r
521                                 return capacity;\r
522                         }\r
523 \r
524                         set {\r
525                                 if (readOnly) {\r
526                                         throw new NotSupportedException\r
527                                                 ("Collection is read-only.");\r
528                                 }\r
529 \r
530                                 if (value < count) {\r
531                                         throw new ArgumentOutOfRangeException\r
532                                                 ("ArrayList Capacity being set to less than Count");\r
533                                 }\r
534 \r
535                                 if (fixedSize && value != capacity) {\r
536                                         throw new NotSupportedException\r
537                                                 ("Collection is fixed size.");\r
538                                 }\r
539 \r
540                                 setSize (value);\r
541                         }\r
542                 }\r
543 \r
544                 private void CheckSourceVersion() {\r
545                         if (null != this.source && this.version != this.source.version) {\r
546                                 throw new InvalidOperationException();\r
547                         }\r
548                 }\r
549 \r
550                 public virtual int Count {\r
551                         get {\r
552                                 CheckSourceVersion();\r
553                                 return count;\r
554                         }\r
555                 }\r
556 \r
557                 public virtual bool IsFixedSize {\r
558                         get {\r
559                                 return fixedSize;\r
560                         }\r
561                 }\r
562 \r
563                 public virtual bool IsReadOnly {\r
564                         get {\r
565                                 return readOnly;\r
566                         }\r
567                 }\r
568 \r
569                 public virtual bool IsSynchronized {\r
570                         get {\r
571                                 return synchronized;\r
572                         }\r
573                 }\r
574 \r
575                 public virtual object this[int index] {\r
576                         get {\r
577                                 CheckSourceVersion();\r
578 \r
579                                 if (index < 0) {\r
580                                         throw new ArgumentOutOfRangeException ("index < 0");\r
581                                 }\r
582 \r
583                                 if (index >= count) {\r
584                                         throw new ArgumentOutOfRangeException ("index out of range");\r
585                                 }\r
586 \r
587                                 return dataArray[index];\r
588                         }\r
589                         set {\r
590                                 if (index < 0) {\r
591                                         throw new ArgumentOutOfRangeException ("index < 0");\r
592                                 }\r
593 \r
594                                 if (index >= count) {\r
595                                         throw new ArgumentOutOfRangeException ("index out of range");\r
596                                 }\r
597 \r
598                                 if (readOnly) {\r
599                                         throw new NotSupportedException ("Collection is read-only.");\r
600                                 }\r
601 \r
602                                 dataArray[index] = value;\r
603                                 version++;\r
604                         }\r
605                 }\r
606 \r
607                 [MonoTODO]\r
608                 public virtual object SyncRoot {\r
609                         get {\r
610                                 throw new NotImplementedException ("System.Collections.ArrayList.SyncRoot.get");\r
611                         }\r
612                 }\r
613 \r
614 \r
615                 // methods\r
616 \r
617                 public virtual int Add (object value) {\r
618                         if (readOnly)\r
619                                 throw new NotSupportedException ("ArrayList is read-only.");\r
620                         if (fixedSize)\r
621                                 throw new NotSupportedException ("ArrayList is fixed size.");\r
622 \r
623                         if (count + 1 >= capacity)\r
624                                 setSize (capacity * 2);\r
625 \r
626                         dataArray[count] = value;\r
627                         version++;\r
628                         return count++;\r
629                 }\r
630 \r
631                 public virtual void AddRange (ICollection c) {\r
632                         if (null == c)\r
633                                 throw new ArgumentNullException ("c");\r
634                         if (readOnly || fixedSize)\r
635                                 throw new NotSupportedException ();\r
636 \r
637                         int cc = c.Count;\r
638                         if (count + cc >= capacity)\r
639                                 Capacity = cc < count? count * 2: count + cc + 1;\r
640                         c.CopyTo (dataArray, count);\r
641                         count += cc;\r
642                         version++;\r
643                 }\r
644 \r
645                 public virtual int BinarySearch (object value) {\r
646                         return BinarySearch (0, count, value, null);\r
647                 }\r
648 \r
649                 public virtual int BinarySearch (object value, IComparer comparer) {\r
650                         return BinarySearch (0, count, value, comparer);\r
651                 }\r
652 \r
653                 public virtual int BinarySearch (int index, int count,\r
654                                                  object value, IComparer comparer) {\r
655                         return Array.BinarySearch (dataArray, index, count, value, comparer);\r
656                 }\r
657 \r
658                 public virtual void Clear () {\r
659                         if (readOnly || fixedSize)\r
660                                 throw new NotSupportedException();\r
661 \r
662                         count = 0;\r
663                         version++;\r
664                 }\r
665 \r
666                 public virtual object Clone () {\r
667                         return new ArrayList (dataArray, count, capacity,\r
668                                               fixedSize, readOnly, synchronized);\r
669                 }\r
670 \r
671                 public virtual bool Contains (object item) {\r
672                         for (int i = 0; i < count; i++) {\r
673                                 if (Object.Equals (dataArray[i], item)) {\r
674                                         return true;\r
675                                 }\r
676                         }\r
677 \r
678                         return false;\r
679                 }\r
680 \r
681                 public virtual void CopyTo (Array array) {\r
682                         if (null == array)\r
683                                 throw new ArgumentNullException("array");\r
684                         if (array.Rank > 1)\r
685                                 throw new ArgumentException("array cannot be multidimensional");\r
686 \r
687                         Array.Copy (dataArray, 0, array, 0, this.count);\r
688                 }\r
689 \r
690                 public virtual void CopyTo (Array array, int arrayIndex) {\r
691                         if (null == array)\r
692                                 throw new ArgumentNullException("array");\r
693                         if (arrayIndex < 0)\r
694                                 throw new ArgumentOutOfRangeException("arrayIndex");\r
695                         if (array.Rank > 1)\r
696                                 throw new ArgumentException("array cannot be multidimensional");\r
697                         if (this.count > array.Length - arrayIndex)\r
698                                 throw new ArgumentException("this ArrayList has more items than the space available in array from arrayIndex to the end of array");\r
699                         \r
700                         Array.Copy (dataArray, 0, array, arrayIndex, this.count);\r
701                 }\r
702 \r
703                 public virtual void CopyTo (int index, Array array,\r
704                                             int arrayIndex, int count) {\r
705                         if (null == array)\r
706                                 throw new ArgumentNullException("array");\r
707                         if (arrayIndex < 0)\r
708                                 throw new ArgumentOutOfRangeException("arrayIndex");\r
709                         if (index < 0)\r
710                                 throw new ArgumentOutOfRangeException("index");\r
711                         if (count < 0)\r
712                                 throw new ArgumentOutOfRangeException("count");\r
713                         if (index >= this.count)\r
714                                 throw new ArgumentException("index is greater than or equal to the source ArrayList.Count");\r
715                         if (array.Rank > 1)\r
716                                 throw new ArgumentException("array cannot be multidimensional");\r
717                         if (arrayIndex >= array.Length)\r
718                                 throw new ArgumentException("arrayIndex is greater than or equal to array's length");\r
719                         if (this.count > array.Length - arrayIndex)\r
720                                 throw new ArgumentException("this ArrayList has more items than the space available in array from arrayIndex to the end of array");\r
721 \r
722                         Array.Copy (dataArray, index, array, arrayIndex, count);\r
723                 }\r
724 \r
725                 [Serializable]\r
726                 private class ArrayListEnumerator : IEnumerator, ICloneable {\r
727                         private object[] data;\r
728                         private int idx;\r
729                         private int start;\r
730                         private int num;\r
731                         private ArrayList enumeratee;\r
732                         private long version;\r
733 \r
734                         internal ArrayListEnumerator(int index, int count, object[] items, ArrayList al, long ver) {\r
735                                 data = items;\r
736                                 start = index;\r
737                                 num = count;\r
738                                 idx = start - 1;\r
739                                 enumeratee = al;\r
740                                 version = ver;\r
741                         }\r
742 \r
743                         public object Clone ()\r
744                         {\r
745                                 return new ArrayListEnumerator (start, num, data, enumeratee, version);\r
746                         }\r
747 \r
748                         public virtual object Current {\r
749                                 get {\r
750                                         return data [idx];\r
751                                 }\r
752                         }\r
753                         public virtual bool MoveNext() {\r
754                                 if (enumeratee.version != version)\r
755                                         throw new InvalidOperationException();\r
756                                 if (++idx < start + num)\r
757                                         return true;\r
758                                 return false;\r
759                         }\r
760                         public virtual void Reset() {\r
761                                 idx = start - 1;\r
762                         }\r
763                 }\r
764 \r
765                 public virtual IEnumerator GetEnumerator () {\r
766                         return new ArrayListEnumerator(0, this.Count, dataArray, this, this.version);\r
767                 }\r
768 \r
769                 private void ValidateRange(int index, int count) {\r
770                         if (index < 0) {\r
771                                 throw new ArgumentOutOfRangeException("index", index, "Must be equal to or greater than zero");\r
772                         }\r
773                         if (count < 0) {\r
774                                 throw new ArgumentOutOfRangeException("count", count, "Must be equal to or greater than zero");\r
775                         }\r
776                         if (index > this.count - 1) {\r
777                                 throw new ArgumentException();\r
778                         }\r
779                         if (index + count > this.count - 1) {\r
780                                 throw new ArgumentException();\r
781                         }\r
782                 }\r
783 \r
784                 public virtual IEnumerator GetEnumerator (int index, int count) {\r
785                         ValidateRange(index, count);\r
786                         return new ArrayListEnumerator(index, count, dataArray, this, this.version);\r
787                 }\r
788 \r
789                 public virtual ArrayList GetRange (int index, int count) {\r
790                         ValidateRange(index, count);\r
791                         ArrayList retVal = new ArrayList(count);\r
792 \r
793                         for (int i = index; i < count + index; i++) {\r
794                                 retVal.Add(this[i]);\r
795                         }\r
796                         retVal.version = this.version;\r
797                         retVal.source = this;\r
798                         return retVal;\r
799                 }\r
800 \r
801                 public virtual int IndexOf (object value) {\r
802                         return IndexOf (value, 0, count);\r
803                 }\r
804 \r
805                 public virtual int IndexOf (object value, int startIndex) {\r
806                         return IndexOf (value, startIndex, count - startIndex);\r
807                 }\r
808 \r
809                 public virtual int IndexOf (object value, int startIndex, int count) {\r
810                         if (startIndex < 0 || startIndex + count > this.count || count < 0) {\r
811                                 throw new ArgumentOutOfRangeException ("IndexOf arguments out of range");\r
812                         }\r
813                         for (int i = startIndex; i < (startIndex + count); i++) {\r
814                                 if (Object.Equals (dataArray[i], value)) {\r
815                                         return i;\r
816                                 }\r
817                         }\r
818 \r
819                         return -1;\r
820                 }\r
821 \r
822                 public virtual void Insert (int index, object value) {\r
823                         if (readOnly) {\r
824                                 throw new NotSupportedException\r
825                                         ("Collection is read-only.");\r
826                         }\r
827 \r
828                         if (fixedSize) {\r
829                                 throw new NotSupportedException\r
830                                         ("Collection is fixed size.");\r
831                         }\r
832 \r
833                         if (index < 0 || index >= capacity) {\r
834                                 throw new ArgumentOutOfRangeException ("index < 0 or index >= capacity");\r
835                         }\r
836 \r
837                         shiftElements (index, 1);\r
838                         dataArray[index] = value;\r
839                         count++;\r
840                         version++;\r
841                 }\r
842 \r
843                 public virtual void InsertRange (int index, ICollection c) {\r
844 \r
845                         if (c == null)\r
846                                 throw new ArgumentNullException ();\r
847 \r
848                         if (index < 0 || index > count)\r
849                                 throw new ArgumentOutOfRangeException ();\r
850 \r
851                         if (IsReadOnly || IsFixedSize)\r
852                                 throw new NotSupportedException ();\r
853 \r
854                         // Get a copy of the collection before the shift in case the collection\r
855                         // is this.  Otherwise the enumerator will be confused.\r
856                         Array source = Array.CreateInstance(typeof(object), c.Count);\r
857                         c.CopyTo(source, 0);\r
858 \r
859                         shiftElements (index, c.Count);\r
860                         count += c.Count;\r
861 \r
862                         foreach (object o in source)\r
863                                 dataArray[index++] = o;\r
864 \r
865                         version++;\r
866                 }\r
867 \r
868                 public virtual int LastIndexOf (object value) {\r
869                         return LastIndexOf (value, count - 1, count);\r
870                 }\r
871 \r
872                 public virtual int LastIndexOf (object value, int startIndex) {\r
873                         if (startIndex < 0 || startIndex > count - 1) {\r
874                                 throw new ArgumentOutOfRangeException("startIndex", startIndex, "");\r
875                         }\r
876                         return LastIndexOf (value, startIndex, startIndex + 1);\r
877                 }\r
878 \r
879                 public virtual int LastIndexOf (object value, int startIndex,\r
880                                                 int count)\r
881                 {\r
882                         if (null == value){\r
883                                 return -1;\r
884                         }\r
885                         if (startIndex >= this.count)\r
886                                 throw new ArgumentOutOfRangeException ("startIndex >= Count");\r
887                         if (count < 0)\r
888                                 throw new ArgumentOutOfRangeException ("count < 0");\r
889                         if (startIndex + 1 < count)\r
890                                 throw new ArgumentOutOfRangeException ("startIndex + 1 < count");\r
891                         \r
892                         int EndIndex = startIndex - count + 1;\r
893                         for (int i = startIndex; i >= EndIndex; i--) {\r
894                                 if (Object.Equals (dataArray[i], value)) {\r
895                                         return i;\r
896                                 }\r
897                         }\r
898 \r
899                         return -1;\r
900                 }\r
901 \r
902                 public virtual void Remove (object obj) {\r
903 \r
904                         if (IsFixedSize || IsReadOnly)\r
905                                 throw new NotSupportedException ();\r
906                         \r
907                         int objIndex = IndexOf (obj);\r
908 \r
909                         if (objIndex == -1) {\r
910                                 // shouldn't an exception be thrown here??\r
911                                 // the MS docs don't indicate one, and testing\r
912                                 // with the MS .net framework doesn't indicate one\r
913                                 return;\r
914                         }\r
915 \r
916                         RemoveRange (objIndex, 1);\r
917                 }\r
918 \r
919                 public virtual void RemoveAt (int index) {\r
920                         RemoveRange (index, 1);\r
921                 }\r
922 \r
923                 public virtual void RemoveRange (int index, int count) {\r
924                         if (readOnly) {\r
925                                 throw new NotSupportedException\r
926                                         ("Collection is read-only.");\r
927                         }\r
928 \r
929                         if (fixedSize) {\r
930                                 throw new NotSupportedException\r
931                                         ("Collection is fixed size.");\r
932                         }\r
933 \r
934                         if (index < 0 || index >= this.count || index + count > this.count) {\r
935                                 throw new ArgumentOutOfRangeException\r
936                                         ("index/count out of range");\r
937                         }\r
938 \r
939                         shiftElements (index, - count);\r
940                         this.count -= count;\r
941                         version++;\r
942                 }\r
943 \r
944                 public virtual void Reverse () {\r
945                         Reverse (0, count);\r
946                 }\r
947 \r
948                 public virtual void Reverse (int index, int count) {\r
949                         if (readOnly) {\r
950                                 throw new NotSupportedException\r
951                                         ("Collection is read-only.");\r
952                         }\r
953 \r
954                         if (index < 0 || index + count > this.count) {\r
955                                 throw new ArgumentOutOfRangeException\r
956                                         ("index/count out of range");\r
957                         }\r
958 \r
959                         Array.Reverse (dataArray, index, count);\r
960                         version++;\r
961                 }\r
962 \r
963                 public virtual void SetRange (int index, ICollection c)\r
964                 {\r
965                         if (c == null)\r
966                                 throw new ArgumentNullException ();\r
967                         if (readOnly)\r
968                                 throw new NotSupportedException ();\r
969                         if (index < 0 || (index + c.Count) > count)\r
970                                 throw new ArgumentOutOfRangeException ();\r
971 \r
972                         c.CopyTo(dataArray, index);\r
973                 }\r
974 \r
975                 public virtual void Sort () {\r
976                         Sort (0, count, null);\r
977                 }\r
978 \r
979                 public virtual void Sort (IComparer comparer) {\r
980                         Sort (0, count, comparer);\r
981                 }\r
982 \r
983                 public virtual void Sort (int index, int count, IComparer comparer) {\r
984                         if (readOnly) {\r
985                                 throw new NotSupportedException\r
986                                         ("Collection is read-only.");\r
987                         }\r
988 \r
989                         if (index < 0 || index + count > this.count) {\r
990                                 throw new ArgumentOutOfRangeException\r
991                                         ("index/count out of range");\r
992                         }\r
993             \r
994                         Array.Sort (dataArray, index, count, comparer);\r
995                         version++;\r
996                 }\r
997 \r
998                 public virtual object[] ToArray() {\r
999                         object[] outArray = new object[count];\r
1000                         Array.Copy (dataArray, outArray, count);\r
1001                         return outArray;\r
1002                 }\r
1003 \r
1004                 public virtual Array ToArray (Type type) {\r
1005                         Array outArray = Array.CreateInstance (type, count);\r
1006                         Array.Copy (dataArray, outArray, count);\r
1007                         return outArray;\r
1008                 }\r
1009 \r
1010                 public virtual void TrimToSize () {\r
1011 \r
1012                         if (IsReadOnly || IsFixedSize)\r
1013                                 throw new NotSupportedException ();\r
1014                         \r
1015                         setSize(count);\r
1016 \r
1017                         version++;\r
1018                 }\r
1019         }\r
1020 }\r