3 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
\r
4 Permission is hereby granted, free of charge, to any person obtaining a copy
\r
5 of this software and associated documentation files (the "Software"), to deal
\r
6 in the Software without restriction, including without limitation the rights
\r
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
8 copies of the Software, and to permit persons to whom the Software is
\r
9 furnished to do so, subject to the following conditions:
\r
11 The above copyright notice and this permission notice shall be included in
\r
12 all copies or substantial portions of the Software.
\r
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
25 using System.Diagnostics;
\r
26 using SCG = System.Collections.Generic;
\r
30 /// An advanced interface to operations on an array. The array is viewed as an
\r
31 /// <see cref="T:C5.IList`1"/> of fixed size, and so all operations that would change the
\r
32 /// size of the array will be invalid (and throw <see cref="T:C5.FixedSizeCollectionException"/>
\r
34 /// <typeparam name="T"></typeparam>
\r
35 public class WrappedArray<T> : IList<T>
\r
37 class InnerList : ArrayList<T>
\r
39 internal InnerList(T[] array) { this.array = array; size = array.Length; }
\r
41 ArrayList<T> innerlist;
\r
42 //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing?
\r
43 WrappedArray<T> underlying;
\r
48 /// <param name="wrappedarray"></param>
\r
49 public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); }
\r
52 WrappedArray(ArrayList<T> arraylist, WrappedArray<T> underlying) { innerlist = arraylist; this.underlying = underlying; }
\r
54 #region IList<T> Members
\r
60 public T First { get { return innerlist.First; } }
\r
66 public T Last { get { return innerlist.Last; } }
\r
71 /// <param name="index"></param>
\r
72 /// <returns></returns>
\r
73 public T this[int index]
\r
75 get { return innerlist[index]; }
\r
76 set { innerlist[index] = value; }
\r
82 /// <param name="filter"></param>
\r
83 /// <returns></returns>
\r
84 public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
\r
89 /// <typeparam name="V"></typeparam>
\r
90 /// <param name="mapper"></param>
\r
91 /// <returns></returns>
\r
92 public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map<V>(mapper); }
\r
97 /// <typeparam name="V"></typeparam>
\r
98 /// <param name="mapper"></param>
\r
99 /// <param name="equalityComparer"></param>
\r
100 /// <returns></returns>
\r
101 public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer) { return innerlist.Map<V>(mapper, equalityComparer); }
\r
104 /// ???? should we throw NotRelevantException
\r
106 /// <value></value>
\r
109 get { throw new FixedSizeCollectionException(); }
\r
110 set { throw new FixedSizeCollectionException(); }
\r
116 public virtual bool IsFixedSize
\r
118 get { return true; }
\r
124 /// <param name="index"></param>
\r
125 /// <param name="item"></param>
\r
126 public void Insert(int index, T item)
\r
128 throw new FixedSizeCollectionException();
\r
134 /// <param name="pointer"></param>
\r
135 /// <param name="item"></param>
\r
136 public void Insert(IList<T> pointer, T item)
\r
138 throw new FixedSizeCollectionException();
\r
144 /// <param name="item"></param>
\r
145 public void InsertFirst(T item)
\r
147 throw new FixedSizeCollectionException();
\r
153 /// <param name="item"></param>
\r
154 public void InsertLast(T item)
\r
156 throw new FixedSizeCollectionException();
\r
162 /// <typeparam name="U"></typeparam>
\r
163 /// <param name="i"></param>
\r
164 /// <param name="items"></param>
\r
165 public void InsertAll<U>(int i, System.Collections.Generic.IEnumerable<U> items) where U : T
\r
167 throw new FixedSizeCollectionException();
\r
173 /// <returns></returns>
\r
176 throw new FixedSizeCollectionException();
\r
182 /// <returns></returns>
\r
183 public T RemoveFirst()
\r
185 throw new FixedSizeCollectionException();
\r
191 /// <returns></returns>
\r
192 public T RemoveLast()
\r
194 throw new FixedSizeCollectionException();
\r
200 /// <param name="start"></param>
\r
201 /// <param name="count"></param>
\r
202 /// <returns></returns>
\r
203 public IList<T> View(int start, int count)
\r
205 return new WrappedArray<T>((ArrayList<T>)innerlist.View(start, count), underlying ?? this);
\r
211 /// <param name="item"></param>
\r
212 /// <returns></returns>
\r
213 public IList<T> ViewOf(T item)
\r
215 return new WrappedArray<T>((ArrayList<T>)innerlist.ViewOf(item), underlying ?? this);
\r
221 /// <param name="item"></param>
\r
222 /// <returns></returns>
\r
223 public IList<T> LastViewOf(T item)
\r
225 return new WrappedArray<T>((ArrayList<T>)innerlist.LastViewOf(item), underlying ?? this);
\r
231 /// <value></value>
\r
232 public IList<T> Underlying { get { return underlying; } }
\r
237 /// <value></value>
\r
238 public int Offset { get { return innerlist.Offset; } }
\r
243 /// <value></value>
\r
244 public bool IsValid { get { return innerlist.IsValid; } }
\r
249 /// <param name="offset"></param>
\r
250 /// <returns></returns>
\r
251 public IList<T> Slide(int offset) { return innerlist.Slide(offset); }
\r
256 /// <param name="offset"></param>
\r
257 /// <param name="size"></param>
\r
258 /// <returns></returns>
\r
259 public IList<T> Slide(int offset, int size) { return innerlist.Slide(offset, size); }
\r
264 /// <param name="offset"></param>
\r
265 /// <returns></returns>
\r
266 public bool TrySlide(int offset) { return innerlist.TrySlide(offset); }
\r
271 /// <param name="offset"></param>
\r
272 /// <param name="size"></param>
\r
273 /// <returns></returns>
\r
274 public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); }
\r
279 /// <param name="otherView"></param>
\r
280 /// <returns></returns>
\r
281 public IList<T> Span(IList<T> otherView) { return innerlist.Span(((WrappedArray<T>)otherView).innerlist); }
\r
286 public void Reverse() { innerlist.Reverse(); }
\r
291 /// <returns></returns>
\r
292 public bool IsSorted() { return innerlist.IsSorted(); }
\r
297 /// <param name="comparer"></param>
\r
298 /// <returns></returns>
\r
299 public bool IsSorted(SCG.IComparer<T> comparer) { return innerlist.IsSorted(comparer); }
\r
304 public void Sort() { innerlist.Sort(); }
\r
309 /// <param name="comparer"></param>
\r
310 public void Sort(SCG.IComparer<T> comparer) { innerlist.Sort(comparer); }
\r
315 public void Shuffle() { innerlist.Shuffle(); }
\r
320 /// <param name="rnd"></param>
\r
321 public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); }
\r
325 #region IIndexed<T> Members
\r
330 /// <value></value>
\r
331 public Speed IndexingSpeed { get { return Speed.Constant; } }
\r
336 /// <param name="start"></param>
\r
337 /// <param name="count"></param>
\r
338 /// <returns></returns>
\r
339 public IDirectedCollectionValue<T> this[int start, int count] { get { return innerlist[start, count]; } }
\r
344 /// <param name="item"></param>
\r
345 /// <returns></returns>
\r
346 public int IndexOf(T item) { return innerlist.IndexOf(item); }
\r
351 /// <param name="item"></param>
\r
352 /// <returns></returns>
\r
353 public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
\r
358 /// <param name="predicate"></param>
\r
359 /// <returns></returns>
\r
360 public int FindIndex(Fun<T, bool> predicate) { return innerlist.FindIndex(predicate); }
\r
365 /// <param name="predicate"></param>
\r
366 /// <returns></returns>
\r
367 public int FindLastIndex(Fun<T, bool> predicate) { return innerlist.FindLastIndex(predicate); }
\r
372 /// <param name="i"></param>
\r
373 /// <returns></returns>
\r
374 public T RemoveAt(int i) { throw new FixedSizeCollectionException(); }
\r
379 /// <param name="start"></param>
\r
380 /// <param name="count"></param>
\r
381 public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); }
\r
385 #region ISequenced<T> Members
\r
390 /// <returns></returns>
\r
391 public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); }
\r
396 /// <param name="that"></param>
\r
397 /// <returns></returns>
\r
398 public bool SequencedEquals(ISequenced<T> that) { return innerlist.SequencedEquals(that); }
\r
402 #region ICollection<T> Members
\r
406 /// <value></value>
\r
407 public Speed ContainsSpeed { get { return Speed.Linear; } }
\r
412 /// <returns></returns>
\r
413 public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); }
\r
418 /// <param name="that"></param>
\r
419 /// <returns></returns>
\r
420 public bool UnsequencedEquals(ICollection<T> that) { return innerlist.UnsequencedEquals(that); }
\r
425 /// <param name="item"></param>
\r
426 /// <returns></returns>
\r
427 public bool Contains(T item) { return innerlist.Contains(item); }
\r
432 /// <param name="item"></param>
\r
433 /// <returns></returns>
\r
434 public int ContainsCount(T item) { return innerlist.ContainsCount(item); }
\r
439 /// <returns></returns>
\r
440 public ICollectionValue<T> UniqueItems() { return innerlist.UniqueItems(); }
\r
445 /// <returns></returns>
\r
446 public ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return innerlist.ItemMultiplicities(); }
\r
451 /// <typeparam name="U"></typeparam>
\r
452 /// <param name="items"></param>
\r
453 /// <returns></returns>
\r
454 public bool ContainsAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
\r
455 { return innerlist.ContainsAll(items); }
\r
460 /// <param name="item"></param>
\r
461 /// <returns></returns>
\r
462 public bool Find(ref T item) { return innerlist.Find(ref item); }
\r
467 /// <param name="item"></param>
\r
468 /// <returns></returns>
\r
469 public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); }
\r
474 /// <param name="item"></param>
\r
475 /// <returns></returns>
\r
476 public bool Update(T item) { throw new FixedSizeCollectionException(); }
\r
481 /// <param name="item"></param>
\r
482 /// <param name="olditem"></param>
\r
483 /// <returns></returns>
\r
484 public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); }
\r
489 /// <param name="item"></param>
\r
490 /// <returns></returns>
\r
491 public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); }
\r
496 /// <param name="item"></param>
\r
497 /// <param name="olditem"></param>
\r
498 /// <returns></returns>
\r
499 public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); }
\r
504 /// <param name="item"></param>
\r
505 /// <returns></returns>
\r
506 public bool Remove(T item) { throw new FixedSizeCollectionException(); }
\r
511 /// <param name="item"></param>
\r
512 /// <param name="removeditem"></param>
\r
513 /// <returns></returns>
\r
514 public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); }
\r
519 /// <param name="item"></param>
\r
520 public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); }
\r
525 /// <typeparam name="U"></typeparam>
\r
526 /// <param name="items"></param>
\r
527 public void RemoveAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
\r
532 public void Clear() { throw new FixedSizeCollectionException(); }
\r
537 /// <typeparam name="U"></typeparam>
\r
538 /// <param name="items"></param>
\r
539 public void RetainAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
\r
543 #region IExtensible<T> Members
\r
547 /// <value></value>
\r
548 public object SyncRoot { get { return innerlist.SyncRoot; } }
\r
553 /// <value></value>
\r
554 public bool IsReadOnly { get { return true; } }
\r
559 /// <value></value>
\r
560 public bool AllowsDuplicates
\r
562 get { return true; }
\r
568 /// <value></value>
\r
569 public SCG.IEqualityComparer<T> EqualityComparer { get { return innerlist.EqualityComparer; } }
\r
574 /// <value></value>
\r
575 public bool DuplicatesByCounting
\r
577 get { return false; }
\r
583 /// <param name="item"></param>
\r
584 /// <returns></returns>
\r
585 public bool Add(T item)
\r
587 throw new FixedSizeCollectionException();
\r
593 /// <typeparam name="U"></typeparam>
\r
594 /// <param name="items"></param>
\r
595 public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
\r
597 throw new FixedSizeCollectionException();
\r
603 /// <returns></returns>
\r
604 public bool Check()
\r
606 return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying);
\r
611 #region ICollectionValue<T> Members
\r
613 /// No listeners may be installed
\r
615 /// <value>0</value>
\r
616 public virtual EventTypeEnum ListenableEvents { get { return 0; } }
\r
619 /// No listeners ever installed
\r
621 /// <value>0</value>
\r
622 public virtual EventTypeEnum ActiveEvents { get { return 0; } }
\r
627 /// <value></value>
\r
628 public event CollectionChangedHandler<T> CollectionChanged
\r
630 add { throw new UnlistenableEventException(); }
\r
631 remove { throw new UnlistenableEventException(); }
\r
637 /// <value></value>
\r
638 public event CollectionClearedHandler<T> CollectionCleared
\r
640 add { throw new UnlistenableEventException(); }
\r
641 remove { throw new UnlistenableEventException(); }
\r
647 /// <value></value>
\r
648 public event ItemsAddedHandler<T> ItemsAdded
\r
650 add { throw new UnlistenableEventException(); }
\r
651 remove { throw new UnlistenableEventException(); }
\r
657 /// <value></value>
\r
658 public event ItemInsertedHandler<T> ItemInserted
\r
660 add { throw new UnlistenableEventException(); }
\r
661 remove { throw new UnlistenableEventException(); }
\r
667 /// <value></value>
\r
668 public event ItemsRemovedHandler<T> ItemsRemoved
\r
670 add { throw new UnlistenableEventException(); }
\r
671 remove { throw new UnlistenableEventException(); }
\r
677 /// <value></value>
\r
678 public event ItemRemovedAtHandler<T> ItemRemovedAt
\r
680 add { throw new UnlistenableEventException(); }
\r
681 remove { throw new UnlistenableEventException(); }
\r
687 /// <value></value>
\r
688 public bool IsEmpty { get { return innerlist.IsEmpty; } }
\r
693 /// <value></value>
\r
694 public int Count { get { return innerlist.Count; } }
\r
699 /// <value></value>
\r
700 public Speed CountSpeed { get { return innerlist.CountSpeed; } }
\r
705 /// <param name="array"></param>
\r
706 /// <param name="index"></param>
\r
707 public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); }
\r
712 /// <returns></returns>
\r
713 public T[] ToArray() { return innerlist.ToArray(); }
\r
718 /// <param name="action"></param>
\r
719 public void Apply(Act<T> action) { innerlist.Apply(action); }
\r
724 /// <param name="predicate"></param>
\r
725 /// <returns></returns>
\r
726 public bool Exists(Fun<T, bool> predicate) { return innerlist.Exists(predicate); }
\r
731 /// <param name="predicate"></param>
\r
732 /// <param name="item"></param>
\r
733 /// <returns></returns>
\r
734 public bool Find(Fun<T, bool> predicate, out T item) { return innerlist.Find(predicate, out item); }
\r
739 /// <param name="predicate"></param>
\r
740 /// <returns></returns>
\r
741 public bool All(Fun<T, bool> predicate) { return innerlist.All(predicate); }
\r
746 /// <returns></returns>
\r
747 public T Choose() { return innerlist.Choose(); }
\r
752 /// <param name="filter"></param>
\r
753 /// <returns></returns>
\r
754 public SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return innerlist.Filter(filter); }
\r
758 #region IEnumerable<T> Members
\r
763 /// <returns></returns>
\r
764 public SCG.IEnumerator<T> GetEnumerator() { return innerlist.GetEnumerator(); }
\r
767 #region IShowable Members
\r
772 /// <param name="stringbuilder"></param>
\r
773 /// <param name="rest"></param>
\r
774 /// <param name="formatProvider"></param>
\r
775 /// <returns></returns>
\r
776 public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
\r
777 { return innerlist.Show(stringbuilder, ref rest, formatProvider); }
\r
781 #region IFormattable Members
\r
786 /// <returns></returns>
\r
787 public override string ToString() { return innerlist.ToString(); }
\r
793 /// <param name="format"></param>
\r
794 /// <param name="formatProvider"></param>
\r
795 /// <returns></returns>
\r
796 public virtual string ToString(string format, IFormatProvider formatProvider) { return innerlist.ToString(format, formatProvider); }
\r
800 #region IDirectedCollectionValue<T> Members
\r
805 /// <returns></returns>
\r
806 public IDirectedCollectionValue<T> Backwards() { return innerlist.Backwards(); }
\r
811 /// <param name="predicate"></param>
\r
812 /// <param name="item"></param>
\r
813 /// <returns></returns>
\r
814 public bool FindLast(Fun<T, bool> predicate, out T item) { return innerlist.FindLast(predicate, out item); }
\r
818 #region IDirectedEnumerable<T> Members
\r
820 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
\r
825 /// <value></value>
\r
826 public EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }
\r
830 #region IDisposable Members
\r
833 /// Dispose this if a view else operation is illegal
\r
835 /// <exception cref="FixedSizeCollectionException">If not a view</exception>
\r
836 public void Dispose()
\r
838 if (underlying == null)
\r
839 throw new FixedSizeCollectionException();
\r
841 innerlist.Dispose();
\r
846 #region ICloneable Members
\r
849 /// Make a shallow copy of this WrappedArray.
\r
853 /// <returns></returns>
\r
854 public virtual object Clone()
\r
856 return new WrappedArray<T>(innerlist.ToArray());
\r
863 #region IEnumerable Members
\r
865 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
\r
867 throw new Exception("The method or operation is not implemented.");
\r