2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 using System.Diagnostics;
25 using SCG = System.Collections.Generic;
29 /// An advanced interface to operations on an array. The array is viewed as an
30 /// <see cref="T:C5.IList`1"/> of fixed size, and so all operations that would change the
31 /// size of the array will be invalid (and throw <see cref="T:C5.FixedSizeCollectionException"/>
33 /// <typeparam name="T"></typeparam>
34 public class WrappedArray<T> : IList<T>, SCG.IList<T>
36 class InnerList : ArrayList<T>
38 internal InnerList(T[] array) { this.array = array; size = array.Length; }
40 ArrayList<T> innerlist;
41 //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing?
42 WrappedArray<T> underlying;
47 /// <param name="wrappedarray"></param>
48 public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); }
51 WrappedArray(ArrayList<T> arraylist, WrappedArray<T> underlying) { innerlist = arraylist; this.underlying = underlying; }
53 #region IList<T> Members
59 public T First { get { return innerlist.First; } }
65 public T Last { get { return innerlist.Last; } }
70 /// <param name="index"></param>
71 /// <returns></returns>
72 public T this[int index]
74 get { return innerlist[index]; }
75 set { innerlist[index] = value; }
81 /// <param name="filter"></param>
82 /// <returns></returns>
83 public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
88 /// <typeparam name="V"></typeparam>
89 /// <param name="mapper"></param>
90 /// <returns></returns>
91 public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map<V>(mapper); }
96 /// <typeparam name="V"></typeparam>
97 /// <param name="mapper"></param>
98 /// <param name="equalityComparer"></param>
99 /// <returns></returns>
100 public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer) { return innerlist.Map<V>(mapper, equalityComparer); }
103 /// ???? should we throw NotRelevantException
108 get { throw new FixedSizeCollectionException(); }
109 set { throw new FixedSizeCollectionException(); }
115 public virtual bool IsFixedSize
123 /// <param name="index"></param>
124 /// <param name="item"></param>
125 public void Insert(int index, T item)
127 throw new FixedSizeCollectionException();
133 /// <param name="pointer"></param>
134 /// <param name="item"></param>
135 public void Insert(IList<T> pointer, T item)
137 throw new FixedSizeCollectionException();
143 /// <param name="item"></param>
144 public void InsertFirst(T item)
146 throw new FixedSizeCollectionException();
152 /// <param name="item"></param>
153 public void InsertLast(T item)
155 throw new FixedSizeCollectionException();
161 /// <typeparam name="U"></typeparam>
162 /// <param name="i"></param>
163 /// <param name="items"></param>
164 public void InsertAll<U>(int i, System.Collections.Generic.IEnumerable<U> items) where U : T
166 throw new FixedSizeCollectionException();
172 /// <returns></returns>
175 throw new FixedSizeCollectionException();
181 /// <returns></returns>
182 public T RemoveFirst()
184 throw new FixedSizeCollectionException();
190 /// <returns></returns>
191 public T RemoveLast()
193 throw new FixedSizeCollectionException();
199 /// <param name="start"></param>
200 /// <param name="count"></param>
201 /// <returns></returns>
202 public IList<T> View(int start, int count)
204 return new WrappedArray<T>((ArrayList<T>)innerlist.View(start, count), underlying ?? this);
210 /// <param name="item"></param>
211 /// <returns></returns>
212 public IList<T> ViewOf(T item)
214 return new WrappedArray<T>((ArrayList<T>)innerlist.ViewOf(item), underlying ?? this);
220 /// <param name="item"></param>
221 /// <returns></returns>
222 public IList<T> LastViewOf(T item)
224 return new WrappedArray<T>((ArrayList<T>)innerlist.LastViewOf(item), underlying ?? this);
231 public IList<T> Underlying { get { return underlying; } }
237 public int Offset { get { return innerlist.Offset; } }
243 public bool IsValid { get { return innerlist.IsValid; } }
248 /// <param name="offset"></param>
249 /// <returns></returns>
250 public IList<T> Slide(int offset) { return innerlist.Slide(offset); }
255 /// <param name="offset"></param>
256 /// <param name="size"></param>
257 /// <returns></returns>
258 public IList<T> Slide(int offset, int size) { return innerlist.Slide(offset, size); }
263 /// <param name="offset"></param>
264 /// <returns></returns>
265 public bool TrySlide(int offset) { return innerlist.TrySlide(offset); }
270 /// <param name="offset"></param>
271 /// <param name="size"></param>
272 /// <returns></returns>
273 public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); }
278 /// <param name="otherView"></param>
279 /// <returns></returns>
280 public IList<T> Span(IList<T> otherView) { return innerlist.Span(((WrappedArray<T>)otherView).innerlist); }
285 public void Reverse() { innerlist.Reverse(); }
290 /// <returns></returns>
291 public bool IsSorted() { return innerlist.IsSorted(); }
296 /// <param name="comparer"></param>
297 /// <returns></returns>
298 public bool IsSorted(SCG.IComparer<T> comparer) { return innerlist.IsSorted(comparer); }
303 public void Sort() { innerlist.Sort(); }
308 /// <param name="comparer"></param>
309 public void Sort(SCG.IComparer<T> comparer) { innerlist.Sort(comparer); }
314 public void Shuffle() { innerlist.Shuffle(); }
319 /// <param name="rnd"></param>
320 public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); }
324 #region IIndexed<T> Members
330 public Speed IndexingSpeed { get { return Speed.Constant; } }
335 /// <param name="start"></param>
336 /// <param name="count"></param>
337 /// <returns></returns>
338 public IDirectedCollectionValue<T> this[int start, int count] { get { return innerlist[start, count]; } }
343 /// <param name="item"></param>
344 /// <returns></returns>
345 public int IndexOf(T item) { return innerlist.IndexOf(item); }
350 /// <param name="item"></param>
351 /// <returns></returns>
352 public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
357 /// <param name="predicate"></param>
358 /// <returns></returns>
359 public int FindIndex(Fun<T, bool> predicate) { return innerlist.FindIndex(predicate); }
364 /// <param name="predicate"></param>
365 /// <returns></returns>
366 public int FindLastIndex(Fun<T, bool> predicate) { return innerlist.FindLastIndex(predicate); }
371 /// <param name="i"></param>
372 /// <returns></returns>
373 public T RemoveAt(int i) { throw new FixedSizeCollectionException(); }
378 /// <param name="start"></param>
379 /// <param name="count"></param>
380 public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); }
384 #region ISequenced<T> Members
389 /// <returns></returns>
390 public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); }
395 /// <param name="that"></param>
396 /// <returns></returns>
397 public bool SequencedEquals(ISequenced<T> that) { return innerlist.SequencedEquals(that); }
401 #region ICollection<T> Members
406 public Speed ContainsSpeed { get { return Speed.Linear; } }
411 /// <returns></returns>
412 public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); }
417 /// <param name="that"></param>
418 /// <returns></returns>
419 public bool UnsequencedEquals(ICollection<T> that) { return innerlist.UnsequencedEquals(that); }
424 /// <param name="item"></param>
425 /// <returns></returns>
426 public bool Contains(T item) { return innerlist.Contains(item); }
431 /// <param name="item"></param>
432 /// <returns></returns>
433 public int ContainsCount(T item) { return innerlist.ContainsCount(item); }
438 /// <returns></returns>
439 public ICollectionValue<T> UniqueItems() { return innerlist.UniqueItems(); }
444 /// <returns></returns>
445 public ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return innerlist.ItemMultiplicities(); }
450 /// <typeparam name="U"></typeparam>
451 /// <param name="items"></param>
452 /// <returns></returns>
453 public bool ContainsAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
454 { return innerlist.ContainsAll(items); }
459 /// <param name="item"></param>
460 /// <returns></returns>
461 public bool Find(ref T item) { return innerlist.Find(ref item); }
466 /// <param name="item"></param>
467 /// <returns></returns>
468 public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); }
473 /// <param name="item"></param>
474 /// <returns></returns>
475 public bool Update(T item) { throw new FixedSizeCollectionException(); }
480 /// <param name="item"></param>
481 /// <param name="olditem"></param>
482 /// <returns></returns>
483 public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); }
488 /// <param name="item"></param>
489 /// <returns></returns>
490 public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); }
495 /// <param name="item"></param>
496 /// <param name="olditem"></param>
497 /// <returns></returns>
498 public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); }
503 /// <param name="item"></param>
504 /// <returns></returns>
505 public bool Remove(T item) { throw new FixedSizeCollectionException(); }
510 /// <param name="item"></param>
511 /// <param name="removeditem"></param>
512 /// <returns></returns>
513 public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); }
518 /// <param name="item"></param>
519 public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); }
524 /// <typeparam name="U"></typeparam>
525 /// <param name="items"></param>
526 public void RemoveAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
531 public void Clear() { throw new FixedSizeCollectionException(); }
536 /// <typeparam name="U"></typeparam>
537 /// <param name="items"></param>
538 public void RetainAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
542 #region IExtensible<T> Members
548 public bool IsReadOnly { get { return true; } }
554 public bool AllowsDuplicates
563 public SCG.IEqualityComparer<T> EqualityComparer { get { return innerlist.EqualityComparer; } }
569 public bool DuplicatesByCounting
571 get { return false; }
577 /// <param name="item"></param>
578 /// <returns></returns>
579 public bool Add(T item)
581 throw new FixedSizeCollectionException();
587 /// <typeparam name="U"></typeparam>
588 /// <param name="items"></param>
589 public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
591 throw new FixedSizeCollectionException();
597 /// <returns></returns>
600 return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying);
605 #region ICollectionValue<T> Members
607 /// No listeners may be installed
610 public virtual EventTypeEnum ListenableEvents { get { return 0; } }
613 /// No listeners ever installed
616 public virtual EventTypeEnum ActiveEvents { get { return 0; } }
622 public event CollectionChangedHandler<T> CollectionChanged
624 add { throw new UnlistenableEventException(); }
625 remove { throw new UnlistenableEventException(); }
632 public event CollectionClearedHandler<T> CollectionCleared
634 add { throw new UnlistenableEventException(); }
635 remove { throw new UnlistenableEventException(); }
642 public event ItemsAddedHandler<T> ItemsAdded
644 add { throw new UnlistenableEventException(); }
645 remove { throw new UnlistenableEventException(); }
652 public event ItemInsertedHandler<T> ItemInserted
654 add { throw new UnlistenableEventException(); }
655 remove { throw new UnlistenableEventException(); }
662 public event ItemsRemovedHandler<T> ItemsRemoved
664 add { throw new UnlistenableEventException(); }
665 remove { throw new UnlistenableEventException(); }
672 public event ItemRemovedAtHandler<T> ItemRemovedAt
674 add { throw new UnlistenableEventException(); }
675 remove { throw new UnlistenableEventException(); }
682 public bool IsEmpty { get { return innerlist.IsEmpty; } }
688 public int Count { get { return innerlist.Count; } }
694 public Speed CountSpeed { get { return innerlist.CountSpeed; } }
699 /// <param name="array"></param>
700 /// <param name="index"></param>
701 public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); }
706 /// <returns></returns>
707 public T[] ToArray() { return innerlist.ToArray(); }
712 /// <param name="action"></param>
713 public void Apply(Act<T> action) { innerlist.Apply(action); }
718 /// <param name="predicate"></param>
719 /// <returns></returns>
720 public bool Exists(Fun<T, bool> predicate) { return innerlist.Exists(predicate); }
725 /// <param name="predicate"></param>
726 /// <param name="item"></param>
727 /// <returns></returns>
728 public bool Find(Fun<T, bool> predicate, out T item) { return innerlist.Find(predicate, out item); }
733 /// <param name="predicate"></param>
734 /// <returns></returns>
735 public bool All(Fun<T, bool> predicate) { return innerlist.All(predicate); }
740 /// <returns></returns>
741 public T Choose() { return innerlist.Choose(); }
746 /// <param name="filter"></param>
747 /// <returns></returns>
748 public SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return innerlist.Filter(filter); }
752 #region IEnumerable<T> Members
757 /// <returns></returns>
758 public SCG.IEnumerator<T> GetEnumerator() { return innerlist.GetEnumerator(); }
761 #region IShowable Members
766 /// <param name="stringbuilder"></param>
767 /// <param name="rest"></param>
768 /// <param name="formatProvider"></param>
769 /// <returns></returns>
770 public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
771 { return innerlist.Show(stringbuilder, ref rest, formatProvider); }
775 #region IFormattable Members
780 /// <returns></returns>
781 public override string ToString() { return innerlist.ToString(); }
787 /// <param name="format"></param>
788 /// <param name="formatProvider"></param>
789 /// <returns></returns>
790 public virtual string ToString(string format, IFormatProvider formatProvider) { return innerlist.ToString(format, formatProvider); }
794 #region IDirectedCollectionValue<T> Members
799 /// <returns></returns>
800 public IDirectedCollectionValue<T> Backwards() { return innerlist.Backwards(); }
805 /// <param name="predicate"></param>
806 /// <param name="item"></param>
807 /// <returns></returns>
808 public bool FindLast(Fun<T, bool> predicate, out T item) { return innerlist.FindLast(predicate, out item); }
812 #region IDirectedEnumerable<T> Members
814 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
820 public EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }
824 #region IDisposable Members
827 /// Dispose this if a view else operation is illegal
829 /// <exception cref="FixedSizeCollectionException">If not a view</exception>
830 public void Dispose()
832 if (underlying == null)
833 throw new FixedSizeCollectionException();
840 #region ICloneable Members
843 /// Make a shallow copy of this WrappedArray.
847 /// <returns></returns>
848 public virtual object Clone()
850 return new WrappedArray<T>(innerlist.ToArray());
855 #region System.Collections.Generic.IList<T> Members
857 void System.Collections.Generic.IList<T>.RemoveAt(int index)
859 throw new FixedSizeCollectionException();
862 void System.Collections.Generic.ICollection<T>.Add(T item)
864 throw new FixedSizeCollectionException();
869 #region System.Collections.ICollection Members
871 bool System.Collections.ICollection.IsSynchronized
873 get { return false; }
877 Object System.Collections.ICollection.SyncRoot
879 get { return ((System.Collections.IList)innerlist).SyncRoot; }
882 void System.Collections.ICollection.CopyTo(Array arr, int index)
884 if (index < 0 || index + Count > arr.Length)
885 throw new ArgumentOutOfRangeException();
887 foreach (T item in this)
888 arr.SetValue(item, index++);
893 #region System.Collections.IList Members
895 Object System.Collections.IList.this[int index]
897 get { return this[index]; }
898 set { this[index] = (T)value; }
901 int System.Collections.IList.Add(Object o)
903 bool added = Add((T)o);
904 // What position to report if item not added? SC.IList.Add doesn't say
905 return added ? Count - 1 : -1;
908 bool System.Collections.IList.Contains(Object o)
910 return Contains((T)o);
913 int System.Collections.IList.IndexOf(Object o)
915 return Math.Max(-1, IndexOf((T)o));
918 void System.Collections.IList.Insert(int index, Object o)
923 void System.Collections.IList.Remove(Object o)
928 void System.Collections.IList.RemoveAt(int index)
935 #region IEnumerable Members
937 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
939 throw new Exception("The method or operation is not implemented.");