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
24 using System.Diagnostics;
\r
25 using SCG = System.Collections.Generic;
\r
29 /// A read-only wrapper class for a generic enumerator
\r
31 public class GuardedEnumerator<T> : SCG.IEnumerator<T>
\r
35 SCG.IEnumerator<T> enumerator;
\r
42 /// Create a wrapper around a generic enumerator
\r
44 /// <param name="enumerator">The enumerator to wrap</param>
\r
45 public GuardedEnumerator(SCG.IEnumerator<T> enumerator)
\r
46 { this.enumerator = enumerator; }
\r
50 #region IEnumerator<T> Members
\r
53 /// Move wrapped enumerator to next item, or the first item if
\r
54 /// this is the first call to MoveNext.
\r
56 /// <returns>True if enumerator is valid now</returns>
\r
57 public bool MoveNext() { return enumerator.MoveNext(); }
\r
61 /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
\r
63 /// <value>The current item of the wrapped enumerator.</value>
\r
64 public T Current { get { return enumerator.Current; } }
\r
68 #region IDisposable Members
\r
70 //TODO: consider possible danger of calling through to Dispose.
\r
72 /// Dispose wrapped enumerator.
\r
74 public void Dispose() { enumerator.Dispose(); }
\r
79 #region IEnumerator Members
\r
81 object System.Collections.IEnumerator.Current
\r
83 get { return enumerator.Current; }
\r
86 void System.Collections.IEnumerator.Reset()
\r
97 /// A read-only wrapper class for a generic enumerable
\r
99 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
101 public class GuardedEnumerable<T> : SCG.IEnumerable<T>
\r
105 SCG.IEnumerable<T> enumerable;
\r
109 #region Constructor
\r
112 /// Wrap an enumerable in a read-only wrapper
\r
114 /// <param name="enumerable">The enumerable to wrap</param>
\r
115 public GuardedEnumerable(SCG.IEnumerable<T> enumerable)
\r
116 { this.enumerable = enumerable; }
\r
120 #region SCG.IEnumerable<T> Members
\r
123 /// Get an enumerator from the wrapped enumerable
\r
125 /// <returns>The enumerator (itself wrapped)</returns>
\r
126 public SCG.IEnumerator<T> GetEnumerator()
\r
127 { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
\r
131 #region IEnumerable Members
\r
133 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
\r
135 return GetEnumerator();
\r
145 /// A read-only wrapper for a generic directed enumerable
\r
147 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
149 public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>
\r
153 IDirectedEnumerable<T> directedenumerable;
\r
157 #region Constructor
\r
160 /// Wrap a directed enumerable in a read-only wrapper
\r
162 /// <param name="directedenumerable">the collection to wrap</param>
\r
163 public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
\r
164 : base(directedenumerable)
\r
165 { this.directedenumerable = directedenumerable; }
\r
169 #region IDirectedEnumerable<T> Members
\r
172 /// Get a enumerable that enumerates the wrapped collection in the opposite direction
\r
174 /// <returns>The mirrored enumerable</returns>
\r
175 public IDirectedEnumerable<T> Backwards()
\r
176 { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
\r
180 /// <code>Forwards</code> if same, else <code>Backwards</code>
\r
182 /// <value>The enumeration direction relative to the original collection.</value>
\r
183 public EnumerationDirection Direction
\r
184 { get { return directedenumerable.Direction; } }
\r
192 /// A read-only wrapper for an ICollectionValue<T>
\r
194 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
196 public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>
\r
200 /// The ListenableEvents value of the wrapped collection
\r
202 /// <value></value>
\r
203 public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }
\r
206 /// The ActiveEvents value of the wrapped collection
\r
208 /// <value></value>
\r
209 public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }
\r
211 ProxyEventBlock<T> eventBlock;
\r
213 /// The change event. Will be raised for every change operation on the collection.
\r
215 public event CollectionChangedHandler<T> CollectionChanged
\r
217 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }
\r
218 remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
\r
222 /// The change event. Will be raised for every change operation on the collection.
\r
224 public event CollectionClearedHandler<T> CollectionCleared
\r
226 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }
\r
227 remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
\r
231 /// The item added event. Will be raised for every individual addition to the collection.
\r
233 public event ItemsAddedHandler<T> ItemsAdded
\r
235 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }
\r
236 remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
\r
240 /// The item added event. Will be raised for every individual addition to the collection.
\r
242 public event ItemInsertedHandler<T> ItemInserted
\r
244 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }
\r
245 remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }
\r
249 /// The item removed event. Will be raised for every individual removal from the collection.
\r
251 public event ItemsRemovedHandler<T> ItemsRemoved
\r
253 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }
\r
254 remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
\r
258 /// The item removed event. Will be raised for every individual removal from the collection.
\r
260 public event ItemRemovedAtHandler<T> ItemRemovedAt
\r
262 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }
\r
263 remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }
\r
269 ICollectionValue<T> collectionvalue;
\r
273 #region Constructor
\r
276 /// Wrap a ICollectionValue<T> in a read-only wrapper
\r
278 /// <param name="collectionvalue">the collection to wrap</param>
\r
279 public GuardedCollectionValue(ICollectionValue<T> collectionvalue)
\r
280 : base(collectionvalue)
\r
281 { this.collectionvalue = collectionvalue; }
\r
285 #region ICollection<T> Members
\r
288 /// Get the size of the wrapped collection
\r
290 /// <value>The size</value>
\r
291 public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }
\r
294 /// Get the size of the wrapped collection
\r
296 /// <value>The size</value>
\r
297 public virtual int Count { get { return collectionvalue.Count; } }
\r
300 /// The value is symbolic indicating the type of asymptotic complexity
\r
301 /// in terms of the size of this collection (worst-case or amortized as
\r
304 /// <value>A characterization of the speed of the
\r
305 /// <code>Count</code> property in this collection.</value>
\r
306 public virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
\r
309 /// Copy the items of the wrapped collection to an array
\r
311 /// <param name="a">The array</param>
\r
312 /// <param name="i">Starting offset</param>
\r
313 public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }
\r
316 /// Create an array from the items of the wrapped collection
\r
318 /// <returns>The array</returns>
\r
319 public virtual T[] ToArray() { return collectionvalue.ToArray(); }
\r
322 /// Apply a delegate to all items of the wrapped enumerable.
\r
324 /// <param name="a">The delegate to apply</param>
\r
325 //TODO: change this to throw an exception?
\r
326 public virtual void Apply(Act<T> a) { collectionvalue.Apply(a); }
\r
330 /// Check if there exists an item that satisfies a
\r
331 /// specific predicate in the wrapped enumerable.
\r
333 /// <param name="filter">A filter delegate
\r
334 /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
\r
335 /// <returns>True is such an item exists</returns>
\r
336 public virtual bool Exists(Fun<T, bool> filter) { return collectionvalue.Exists(filter); }
\r
341 /// <param name="filter"></param>
\r
342 /// <param name="item"></param>
\r
343 /// <returns></returns>
\r
344 public virtual bool Find(Fun<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }
\r
347 /// Check if all items in the wrapped enumerable satisfies a specific predicate.
\r
349 /// <param name="filter">A filter delegate
\r
350 /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
\r
351 /// <returns>True if all items satisfies the predicate</returns>
\r
352 public virtual bool All(Fun<T, bool> filter) { return collectionvalue.All(filter); }
\r
355 /// Create an enumerable, enumerating the items of this collection that satisfies
\r
356 /// a certain condition.
\r
358 /// <param name="filter">The T->bool filter delegate defining the condition</param>
\r
359 /// <returns>The filtered enumerable</returns>
\r
360 public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return collectionvalue.Filter(filter); }
\r
363 /// Choose some item of this collection.
\r
365 /// <exception cref="NoSuchItemException">if collection is empty.</exception>
\r
366 /// <returns></returns>
\r
367 public virtual T Choose() { return collectionvalue.Choose(); }
\r
371 #region IShowable Members
\r
376 /// <param name="stringbuilder"></param>
\r
377 /// <param name="formatProvider"></param>
\r
378 /// <param name="rest"></param>
\r
379 /// <returns></returns>
\r
380 public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
\r
382 return collectionvalue.Show(stringbuilder, ref rest, formatProvider);
\r
386 #region IFormattable Members
\r
391 /// <param name="format"></param>
\r
392 /// <param name="formatProvider"></param>
\r
393 /// <returns></returns>
\r
394 public string ToString(string format, IFormatProvider formatProvider)
\r
396 return collectionvalue.ToString(format, formatProvider);
\r
405 /// A read-only wrapper for a directed collection
\r
407 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
409 public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>
\r
413 IDirectedCollectionValue<T> directedcollection;
\r
417 #region Constructor
\r
420 /// Wrap a directed collection in a read-only wrapper
\r
422 /// <param name="directedcollection">the collection to wrap</param>
\r
423 public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)
\r
425 base(directedcollection)
\r
426 { this.directedcollection = directedcollection; }
\r
430 #region IDirectedCollection<T> Members
\r
433 /// Get a collection that enumerates the wrapped collection in the opposite direction
\r
435 /// <returns>The mirrored collection</returns>
\r
436 public virtual IDirectedCollectionValue<T> Backwards()
\r
437 { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
\r
442 /// <param name="predicate"></param>
\r
443 /// <param name="item"></param>
\r
444 /// <returns></returns>
\r
445 public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }
\r
449 #region IDirectedEnumerable<T> Members
\r
451 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
\r
452 { return Backwards(); }
\r
456 /// <code>Forwards</code> if same, else <code>Backwards</code>
\r
458 /// <value>The enumeration direction relative to the original collection.</value>
\r
459 public EnumerationDirection Direction
\r
460 { get { return directedcollection.Direction; } }
\r
468 /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,
\r
470 /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>
\r
471 /// and <see cref="T:C5.HashBag`1"/> </i></para>
\r
473 public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>
\r
477 ICollection<T> collection;
\r
481 #region Constructor
\r
484 /// Wrap an ICollection<T> in a read-only wrapper
\r
486 /// <param name="collection">the collection to wrap</param>
\r
487 public GuardedCollection(ICollection<T> collection)
\r
490 this.collection = collection;
\r
495 #region ICollection<T> Members
\r
498 /// (This is a read-only wrapper)
\r
500 /// <value>True</value>
\r
501 public virtual bool IsReadOnly { get { return true; } }
\r
504 /// <summary> </summary>
\r
505 /// <value>Speed of wrapped collection</value>
\r
506 public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
\r
511 /// <returns></returns>
\r
512 public virtual int GetUnsequencedHashCode()
\r
513 { return collection.GetUnsequencedHashCode(); }
\r
518 /// <param name="that"></param>
\r
519 /// <returns></returns>
\r
520 public virtual bool UnsequencedEquals(ICollection<T> that)
\r
521 { return collection.UnsequencedEquals(that); }
\r
525 /// Check if an item is in the wrapped collection
\r
527 /// <param name="item">The item</param>
\r
528 /// <returns>True if found</returns>
\r
529 public virtual bool Contains(T item) { return collection.Contains(item); }
\r
533 /// Count the number of times an item appears in the wrapped collection
\r
535 /// <param name="item">The item</param>
\r
536 /// <returns>The number of copies</returns>
\r
537 public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }
\r
542 /// <returns></returns>
\r
543 public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }
\r
548 /// <returns></returns>
\r
549 public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }
\r
552 /// Check if all items in the argument is in the wrapped collection
\r
554 /// <param name="items">The items</param>
\r
555 /// <typeparam name="U"></typeparam>
\r
556 /// <returns>True if so</returns>
\r
557 public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T { return collection.ContainsAll(items); }
\r
560 /// Search for an item in the wrapped collection
\r
562 /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
\r
563 /// <returns></returns>
\r
564 public virtual bool Find(ref T item) { return collection.Find(ref item); }
\r
569 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
570 /// <param name="item"></param>
\r
571 /// <returns></returns>
\r
572 public virtual bool FindOrAdd(ref T item)
\r
573 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
578 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
579 /// <param name="item"></param>
\r
580 /// <returns></returns>
\r
581 public virtual bool Update(T item)
\r
582 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
587 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
588 /// <param name="item"></param>
\r
589 /// <param name="olditem"></param>
\r
590 /// <returns></returns>
\r
591 public virtual bool Update(T item, out T olditem)
\r
592 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
597 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
598 /// <param name="item"></param>
\r
599 /// <returns></returns>
\r
600 public virtual bool UpdateOrAdd(T item)
\r
601 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
606 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
607 /// <param name="item"></param>
\r
608 /// <param name="olditem"></param>
\r
609 /// <returns></returns>
\r
610 public virtual bool UpdateOrAdd(T item, out T olditem)
\r
611 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
615 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
616 /// <param name="item"></param>
\r
617 /// <returns></returns>
\r
618 public virtual bool Remove(T item)
\r
619 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
624 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
625 /// <param name="item">The value to remove.</param>
\r
626 /// <param name="removeditem">The removed value.</param>
\r
627 /// <returns></returns>
\r
628 public virtual bool Remove(T item, out T removeditem)
\r
629 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
634 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
635 /// <param name="item"></param>
\r
636 public virtual void RemoveAllCopies(T item)
\r
637 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
642 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
643 /// <typeparam name="U"></typeparam>
\r
644 /// <param name="items"></param>
\r
645 public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
\r
646 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
650 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
651 public virtual void Clear()
\r
652 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
657 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
658 /// <typeparam name="U"></typeparam>
\r
659 /// <param name="items"></param>
\r
660 public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
\r
661 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
664 /// Check wrapped collection for internal consistency
\r
666 /// <returns>True if check passed</returns>
\r
667 public virtual bool Check() { return collection.Check(); }
\r
671 #region IExtensible<T> Members
\r
673 /// <summary> </summary>
\r
674 /// <value>False if wrapped collection has set semantics</value>
\r
675 public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
\r
677 //TODO: the equalityComparer should be guarded
\r
681 /// <value></value>
\r
682 public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }
\r
685 /// By convention this is true for any collection with set semantics.
\r
687 /// <value>True if only one representative of a group of equal items
\r
688 /// is kept in the collection together with the total count.</value>
\r
689 public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }
\r
692 /// <summary> </summary>
\r
693 /// <value>True if wrapped collection is empty</value>
\r
694 public override bool IsEmpty { get { return collection.IsEmpty; } }
\r
699 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
700 /// <param name="item"></param>
\r
701 /// <returns></returns>
\r
702 public virtual bool Add(T item)
\r
703 { throw new ReadOnlyCollectionException(); }
\r
708 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
709 /// <typeparam name="U"></typeparam>
\r
710 /// <param name="items"></param>
\r
711 public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
\r
712 { throw new ReadOnlyCollectionException(); }
\r
716 #region ICloneable Members
\r
721 /// <returns></returns>
\r
722 public virtual object Clone()
\r
724 return new GuardedCollection<T>((ICollection<T>)(collection.Clone()));
\r
733 /// A read-only wrapper for a sequenced collection
\r
735 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
737 public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>
\r
741 ISequenced<T> sequenced;
\r
745 #region Constructor
\r
748 /// Wrap a sequenced collection in a read-only wrapper
\r
750 /// <param name="sorted"></param>
\r
751 public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }
\r
756 /// Check if there exists an item that satisfies a
\r
757 /// specific predicate in this collection and return the index of the first one.
\r
759 /// <param name="predicate">A delegate
\r
760 /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
\r
761 /// <returns>the index, if found, a negative value else</returns>
\r
762 public int FindIndex(Fun<T, bool> predicate)
\r
764 IIndexed<T> indexed = sequenced as IIndexed<T>;
\r
765 if (indexed != null)
\r
766 return indexed.FindIndex(predicate);
\r
768 foreach (T item in this)
\r
770 if (predicate(item))
\r
778 /// Check if there exists an item that satisfies a
\r
779 /// specific predicate in this collection and return the index of the last one.
\r
781 /// <param name="predicate">A delegate
\r
782 /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
\r
783 /// <returns>the index, if found, a negative value else</returns>
\r
784 public int FindLastIndex(Fun<T, bool> predicate)
\r
786 IIndexed<T> indexed = sequenced as IIndexed<T>;
\r
787 if (indexed != null)
\r
788 return indexed.FindLastIndex(predicate);
\r
789 int index = Count - 1;
\r
790 foreach (T item in Backwards())
\r
792 if (predicate(item))
\r
801 #region ISequenced<T> Members
\r
806 /// <returns></returns>
\r
807 public int GetSequencedHashCode()
\r
808 { return sequenced.GetSequencedHashCode(); }
\r
813 /// <param name="that"></param>
\r
814 /// <returns></returns>
\r
815 public bool SequencedEquals(ISequenced<T> that)
\r
816 { return sequenced.SequencedEquals(that); }
\r
820 #region IDirectedCollection<T> Members
\r
823 /// Get a collection that enumerates the wrapped collection in the opposite direction
\r
825 /// <returns>The mirrored collection</returns>
\r
826 public virtual IDirectedCollectionValue<T> Backwards()
\r
827 { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
\r
832 /// <param name="predicate"></param>
\r
833 /// <param name="item"></param>
\r
834 /// <returns></returns>
\r
835 public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }
\r
839 #region IDirectedEnumerable<T> Members
\r
841 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
\r
842 { return Backwards(); }
\r
847 /// <code>Forwards</code> if same, else <code>Backwards</code>
\r
849 /// <value>The enumeration direction relative to the original collection.</value>
\r
850 public EnumerationDirection Direction
\r
851 { get { return EnumerationDirection.Forwards; } }
\r
855 #region ICloneable Members
\r
860 /// <returns></returns>
\r
861 public override object Clone()
\r
863 return new GuardedCollection<T>((ISequenced<T>)(sequenced.Clone()));
\r
872 /// A read-only wrapper for a sorted collection
\r
874 /// <i>This is mainly interesting as a base of other guard classes</i>
\r
876 public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>
\r
884 #region Constructor
\r
887 /// Wrap a sorted collection in a read-only wrapper
\r
889 /// <param name="sorted"></param>
\r
890 public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }
\r
894 #region ISorted<T> Members
\r
897 /// Find the predecessor of the item in the wrapped sorted collection
\r
899 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
\r
900 /// <param name="item">The item</param>
\r
901 /// <returns>The predecessor</returns>
\r
902 public T Predecessor(T item) { return sorted.Predecessor(item); }
\r
906 /// Find the Successor of the item in the wrapped sorted collection
\r
908 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
\r
909 /// <param name="item">The item</param>
\r
910 /// <returns>The Successor</returns>
\r
911 public T Successor(T item) { return sorted.Successor(item); }
\r
915 /// Find the weak predecessor of the item in the wrapped sorted collection
\r
917 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
\r
918 /// <param name="item">The item</param>
\r
919 /// <returns>The weak predecessor</returns>
\r
920 public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
\r
924 /// Find the weak Successor of the item in the wrapped sorted collection
\r
926 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
\r
927 /// <param name="item">The item</param>
\r
928 /// <returns>The weak Successor</returns>
\r
929 public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
\r
933 /// Run Cut on the wrapped sorted collection
\r
935 /// <param name="c"></param>
\r
936 /// <param name="low"></param>
\r
937 /// <param name="lval"></param>
\r
938 /// <param name="high"></param>
\r
939 /// <param name="hval"></param>
\r
940 /// <returns></returns>
\r
941 public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
\r
942 { return sorted.Cut(c, out low, out lval, out high, out hval); }
\r
946 /// Get the specified range from the wrapped collection.
\r
947 /// (The current implementation erroneously does not wrap the result.)
\r
949 /// <param name="bot"></param>
\r
950 /// <returns></returns>
\r
951 public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
\r
955 /// Get the specified range from the wrapped collection.
\r
956 /// (The current implementation erroneously does not wrap the result.)
\r
958 /// <param name="bot"></param>
\r
959 /// <param name="top"></param>
\r
960 /// <returns></returns>
\r
961 public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
\r
962 { return sorted.RangeFromTo(bot, top); }
\r
966 /// Get the specified range from the wrapped collection.
\r
967 /// (The current implementation erroneously does not wrap the result.)
\r
969 /// <param name="top"></param>
\r
970 /// <returns></returns>
\r
971 public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
\r
975 /// Get the specified range from the wrapped collection.
\r
976 /// (The current implementation erroneously does not wrap the result.)
\r
978 /// <returns></returns>
\r
979 public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
\r
983 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
984 /// <param name="items"></param>
\r
985 /// <typeparam name="U"></typeparam>
\r
986 public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
\r
987 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
991 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
992 /// <param name="low"></param>
\r
993 public void RemoveRangeFrom(T low)
\r
994 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
999 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1000 /// <param name="low"></param>
\r
1001 /// <param name="hi"></param>
\r
1002 public void RemoveRangeFromTo(T low, T hi)
\r
1003 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1008 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1009 /// <param name="hi"></param>
\r
1010 public void RemoveRangeTo(T hi)
\r
1011 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1015 #region IPriorityQueue<T> Members
\r
1018 /// Find the minimum of the wrapped collection
\r
1020 /// <returns>The minimum</returns>
\r
1021 public T FindMin() { return sorted.FindMin(); }
\r
1026 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1027 /// <returns></returns>
\r
1028 public T DeleteMin()
\r
1029 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1033 /// Find the maximum of the wrapped collection
\r
1035 /// <returns>The maximum</returns>
\r
1036 public T FindMax() { return sorted.FindMax(); }
\r
1041 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1042 /// <returns></returns>
\r
1043 public T DeleteMax()
\r
1044 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1046 //TODO: we should guard the comparer!
\r
1048 /// The comparer object supplied at creation time for the underlying collection
\r
1050 /// <value>The comparer</value>
\r
1051 public SCG.IComparer<T> Comparer { get { return sorted.Comparer; } }
\r
1054 #region IDirectedEnumerable<T> Members
\r
1056 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
\r
1057 { return Backwards(); }
\r
1064 /// <returns></returns>
\r
1065 public override object Clone()
\r
1067 return new GuardedSorted<T>((ISorted<T>)(sorted.Clone()));
\r
1075 /// Read-only wrapper for indexed sorted collections
\r
1077 /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>
\r
1079 public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>
\r
1083 IIndexedSorted<T> indexedsorted;
\r
1087 #region Constructor
\r
1090 /// Wrap an indexed sorted collection in a read-only wrapper
\r
1092 /// <param name="list">the indexed sorted collection</param>
\r
1093 public GuardedIndexedSorted(IIndexedSorted<T> list)
\r
1095 { this.indexedsorted = list; }
\r
1099 #region IIndexedSorted<T> Members
\r
1102 /// Get the specified range from the wrapped collection.
\r
1103 /// (The current implementation erroneously does not wrap the result.)
\r
1105 /// <param name="bot"></param>
\r
1106 /// <returns></returns>
\r
1107 public new IDirectedCollectionValue<T> RangeFrom(T bot)
\r
1108 { return indexedsorted.RangeFrom(bot); }
\r
1112 /// Get the specified range from the wrapped collection.
\r
1113 /// (The current implementation erroneously does not wrap the result.)
\r
1115 /// <param name="bot"></param>
\r
1116 /// <param name="top"></param>
\r
1117 /// <returns></returns>
\r
1118 public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
\r
1119 { return indexedsorted.RangeFromTo(bot, top); }
\r
1123 /// Get the specified range from the wrapped collection.
\r
1124 /// (The current implementation erroneously does not wrap the result.)
\r
1126 /// <param name="top"></param>
\r
1127 /// <returns></returns>
\r
1128 public new IDirectedCollectionValue<T> RangeTo(T top)
\r
1129 { return indexedsorted.RangeTo(top); }
\r
1133 /// Report the number of items in the specified range of the wrapped collection
\r
1135 /// <param name="bot"></param>
\r
1136 /// <returns></returns>
\r
1137 public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
\r
1141 /// Report the number of items in the specified range of the wrapped collection
\r
1143 /// <param name="bot"></param>
\r
1144 /// <param name="top"></param>
\r
1145 /// <returns></returns>
\r
1146 public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
\r
1150 /// Report the number of items in the specified range of the wrapped collection
\r
1152 /// <param name="top"></param>
\r
1153 /// <returns></returns>
\r
1154 public int CountTo(T top) { return indexedsorted.CountTo(top); }
\r
1158 /// Run FindAll on the wrapped collection with the indicated filter.
\r
1159 /// The result will <b>not</b> be read-only.
\r
1161 /// <param name="f"></param>
\r
1162 /// <returns></returns>
\r
1163 public IIndexedSorted<T> FindAll(Fun<T, bool> f)
\r
1164 { return indexedsorted.FindAll(f); }
\r
1168 /// Run Map on the wrapped collection with the indicated mapper.
\r
1169 /// The result will <b>not</b> be read-only.
\r
1171 /// <param name="m"></param>
\r
1172 /// <param name="c">The comparer to use in the result</param>
\r
1173 /// <returns></returns>
\r
1174 public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)
\r
1175 { return indexedsorted.Map(m, c); }
\r
1179 #region IIndexed<T> Members
\r
1184 /// <value>The i'th item of the wrapped sorted collection</value>
\r
1185 public T this[int i] { get { return indexedsorted[i]; } }
\r
1190 /// <value></value>
\r
1191 public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }
\r
1193 /// <summary> </summary>
\r
1194 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
\r
1195 public IDirectedCollectionValue<T> this[int start, int end]
\r
1196 { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
\r
1200 /// Find the (first) index of an item in the wrapped collection
\r
1202 /// <param name="item"></param>
\r
1203 /// <returns></returns>
\r
1204 public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
\r
1208 /// Find the last index of an item in the wrapped collection
\r
1210 /// <param name="item"></param>
\r
1211 /// <returns></returns>
\r
1212 public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
\r
1217 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1218 /// <param name="i"></param>
\r
1219 /// <returns></returns>
\r
1220 public T RemoveAt(int i)
\r
1221 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1226 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1227 /// <param name="start"></param>
\r
1228 /// <param name="count"></param>
\r
1229 public void RemoveInterval(int start, int count)
\r
1230 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1234 #region IDirectedEnumerable<T> Members
\r
1236 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
\r
1237 { return Backwards(); }
\r
1244 /// <returns></returns>
\r
1245 public override object Clone()
\r
1247 return new GuardedIndexedSorted<T>((IIndexedSorted<T>)(indexedsorted.Clone()));
\r
1255 /// A read-only wrapper for a generic list collection
\r
1256 /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
\r
1257 /// <see cref="T:C5.LinkedList`1"/>,
\r
1258 /// <see cref="T:C5.HashedLinkedList`1"/>,
\r
1259 /// <see cref="T:C5.ArrayList`1"/> or
\r
1260 /// <see cref="T:C5.HashedArray`1"/>.
\r
1263 public class GuardedList<T> : GuardedSequenced<T>, IList<T>
\r
1267 IList<T> innerlist;
\r
1268 GuardedList<T> underlying;
\r
1269 bool slidableView = false;
\r
1273 #region Constructor
\r
1276 /// Wrap a list in a read-only wrapper
\r
1278 /// <param name="list">The list</param>
\r
1279 public GuardedList(IList<T> list)
\r
1282 this.innerlist = list;
\r
1283 if (list.Underlying != null)
\r
1284 underlying = new GuardedList<T>(list.Underlying, null, false);
\r
1287 GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)
\r
1290 this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;
\r
1294 #region IList<T> Members
\r
1299 /// <value>The first item of the wrapped list</value>
\r
1300 public T First { get { return innerlist.First; } }
\r
1306 /// <value>The last item of the wrapped list</value>
\r
1307 public T Last { get { return innerlist.Last; } }
\r
1312 /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
\r
1313 /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
\r
1316 get { return innerlist.FIFO; }
\r
1317 set { throw new ReadOnlyCollectionException("List is read only"); }
\r
1323 public virtual bool IsFixedSize
\r
1325 get { return true; }
\r
1331 /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
\r
1332 /// <value>The i'th item of the wrapped list</value>
\r
1333 public T this[int i]
\r
1335 get { return innerlist[i]; }
\r
1336 set { throw new ReadOnlyCollectionException("List is read only"); }
\r
1342 /// <value></value>
\r
1343 public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }
\r
1347 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1348 /// <param name="i"></param>
\r
1349 /// <param name="item"></param>
\r
1350 public void Insert(int i, T item)
\r
1351 { throw new ReadOnlyCollectionException(); }
\r
1355 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1356 /// <param name="pointer"></param>
\r
1357 /// <param name="item"></param>
\r
1358 public void Insert(IList<T> pointer, T item)
\r
1359 { throw new ReadOnlyCollectionException(); }
\r
1363 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1364 /// <param name="item"></param>
\r
1365 public void InsertFirst(T item)
\r
1366 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1370 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1371 /// <param name="item"></param>
\r
1372 public void InsertLast(T item)
\r
1373 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1377 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1378 /// <param name="item"></param>
\r
1379 /// <param name="target"></param>
\r
1380 public void InsertBefore(T item, T target)
\r
1381 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1386 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1387 /// <param name="item"></param>
\r
1388 /// <param name="target"></param>
\r
1389 public void InsertAfter(T item, T target)
\r
1390 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1395 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1396 /// <param name="i"></param>
\r
1397 /// <param name="items"></param>
\r
1398 public void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
\r
1399 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1403 /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
\r
1405 /// <param name="filter">The filter to use</param>
\r
1406 /// <returns></returns>
\r
1407 public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
\r
1411 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
\r
1413 /// <typeparam name="V">The type of items of the new list</typeparam>
\r
1414 /// <param name="mapper">The mapper to use.</param>
\r
1415 /// <returns>The mapped list</returns>
\r
1416 public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map(mapper); }
\r
1419 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
\r
1421 /// <typeparam name="V">The type of items of the new list</typeparam>
\r
1422 /// <param name="mapper">The delegate defining the map.</param>
\r
1423 /// <param name="itemequalityComparer">The itemequalityComparer to use for the new list</param>
\r
1424 /// <returns>The new list.</returns>
\r
1425 public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }
\r
1429 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1430 /// <returns></returns>
\r
1431 public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }
\r
1436 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1437 /// <returns></returns>
\r
1438 public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }
\r
1443 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1444 /// <returns></returns>
\r
1445 public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }
\r
1449 /// Create the indicated view on the wrapped list and wrap it read-only.
\r
1451 /// <param name="start"></param>
\r
1452 /// <param name="count"></param>
\r
1453 /// <returns></returns>
\r
1454 public IList<T> View(int start, int count)
\r
1456 IList<T> view = innerlist.View(start, count);
\r
1457 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
\r
1461 /// Create the indicated view on the wrapped list and wrap it read-only.
\r
1463 /// <param name="item"></param>
\r
1464 /// <returns></returns>
\r
1465 public IList<T> ViewOf(T item)
\r
1467 IList<T> view = innerlist.ViewOf(item);
\r
1468 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
\r
1472 /// Create the indicated view on the wrapped list and wrap it read-only.
\r
1474 /// <param name="item"></param>
\r
1475 /// <returns></returns>
\r
1476 public IList<T> LastViewOf(T item)
\r
1478 IList<T> view = innerlist.LastViewOf(item);
\r
1479 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
\r
1485 /// <value>The wrapped underlying list of the wrapped view </value>
\r
1486 public IList<T> Underlying { get { return underlying; } }
\r
1492 /// <value>The offset of the wrapped list as a view.</value>
\r
1493 public int Offset { get { return innerlist.Offset; } }
\r
1498 /// <value></value>
\r
1499 public virtual bool IsValid { get { return innerlist.IsValid; } }
\r
1503 /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>
\r
1504 /// <param name="offset"></param>
\r
1505 public IList<T> Slide(int offset)
\r
1509 innerlist.Slide(offset);
\r
1513 throw new ReadOnlyCollectionException("List is read only");
\r
1519 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1520 /// <param name="offset"></param>
\r
1521 /// <param name="size"></param>
\r
1522 public IList<T> Slide(int offset, int size)
\r
1526 innerlist.Slide(offset, size);
\r
1530 throw new ReadOnlyCollectionException("List is read only");
\r
1537 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1538 /// <param name="offset"></param>
\r
1539 /// <returns></returns>
\r
1540 public bool TrySlide(int offset)
\r
1543 return innerlist.TrySlide(offset);
\r
1545 throw new ReadOnlyCollectionException("List is read only");
\r
1551 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1552 /// <param name="offset"></param>
\r
1553 /// <param name="size"></param>
\r
1554 /// <returns></returns>
\r
1555 public bool TrySlide(int offset, int size)
\r
1558 return innerlist.TrySlide(offset, size);
\r
1560 throw new ReadOnlyCollectionException("List is read only");
\r
1566 /// <param name="otherView"></param>
\r
1567 /// <returns></returns>
\r
1568 public IList<T> Span(IList<T> otherView)
\r
1570 GuardedList<T> otherGuardedList = otherView as GuardedList<T>;
\r
1571 if (otherGuardedList == null)
\r
1572 throw new IncompatibleViewException();
\r
1573 IList<T> span = innerlist.Span(otherGuardedList.innerlist);
\r
1576 return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);
\r
1580 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1582 public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }
\r
1587 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1588 /// <param name="start"></param>
\r
1589 /// <param name="count"></param>
\r
1590 public void Reverse(int start, int count)
\r
1591 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1595 /// Check if wrapped list is sorted according to the default sorting order
\r
1596 /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class
\r
1598 /// <exception cref="NotComparableException">if T is not comparable</exception>
\r
1599 /// <returns>True if the list is sorted, else false.</returns>
\r
1600 public bool IsSorted() { return innerlist.IsSorted(Comparer<T>.Default); }
\r
1603 /// Check if wrapped list is sorted
\r
1605 /// <param name="c">The sorting order to use</param>
\r
1606 /// <returns>True if sorted</returns>
\r
1607 public bool IsSorted(SCG.IComparer<T> c) { return innerlist.IsSorted(c); }
\r
1612 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1613 public void Sort()
\r
1614 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1619 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1620 /// <param name="c"></param>
\r
1621 public void Sort(SCG.IComparer<T> c)
\r
1622 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1626 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1627 public void Shuffle()
\r
1628 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1633 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1634 /// <param name="rnd"></param>
\r
1635 public void Shuffle(Random rnd)
\r
1636 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1640 #region IIndexed<T> Members
\r
1642 /// <summary> </summary>
\r
1643 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
\r
1644 public IDirectedCollectionValue<T> this[int start, int end]
\r
1645 { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }
\r
1649 /// Find the (first) index of an item in the wrapped collection
\r
1651 /// <param name="item"></param>
\r
1652 /// <returns></returns>
\r
1653 public int IndexOf(T item) { return innerlist.IndexOf(item); }
\r
1657 /// Find the last index of an item in the wrapped collection
\r
1659 /// <param name="item"></param>
\r
1660 /// <returns></returns>
\r
1661 public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
\r
1666 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1667 /// <param name="i"></param>
\r
1668 /// <returns></returns>
\r
1669 public T RemoveAt(int i)
\r
1670 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1675 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1676 /// <param name="start"></param>
\r
1677 /// <param name="count"></param>
\r
1678 public void RemoveInterval(int start, int count)
\r
1679 { throw new ReadOnlyCollectionException("List is read only"); }
\r
1683 #region IDirectedEnumerable<T> Members
\r
1685 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
\r
1686 { return Backwards(); }
\r
1690 #region IStack<T> Members
\r
1696 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1697 /// <returns>-</returns>
\r
1698 public void Push(T item)
\r
1699 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1704 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1705 /// <returns>-</returns>
\r
1707 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1711 #region IQueue<T> Members
\r
1716 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1717 /// <returns>-</returns>
\r
1718 public void Enqueue(T item)
\r
1719 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1724 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1725 /// <returns>-</returns>
\r
1726 public T Dequeue()
\r
1727 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
\r
1731 #region IDisposable Members
\r
1734 /// Ignore: this may be called by a foreach or using statement.
\r
1736 public void Dispose() { }
\r
1743 /// <returns></returns>
\r
1744 public override object Clone()
\r
1746 return new GuardedList<T>((IList<T>)(innerlist.Clone()));
\r
1752 /// A read-only wrapper for a generic indexable queue (allows indexing).
\r
1754 /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>
\r
1756 /// <typeparam name="T">The item type.</typeparam>
\r
1757 public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>
\r
1765 #region Constructor
\r
1768 /// Wrap a queue in a read-only wrapper
\r
1770 /// <param name="queue">The queue</param>
\r
1771 public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }
\r
1775 #region IQueue<T> Members
\r
1779 /// <value></value>
\r
1780 public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }
\r
1783 /// Index into the wrapped queue
\r
1785 /// <param name="i"></param>
\r
1786 /// <returns></returns>
\r
1787 public T this[int i] { get { return queue[i]; } }
\r
1792 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1793 /// <returns>-</returns>
\r
1794 public void Enqueue(T item)
\r
1795 { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
\r
1800 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1801 /// <returns>-</returns>
\r
1802 public T Dequeue()
\r
1803 { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
\r
1809 /// A read-only wrapper for a dictionary.
\r
1811 /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>
\r
1813 public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>
\r
1817 IDictionary<K, V> dict;
\r
1821 #region Constructor
\r
1824 /// Wrap a dictionary in a read-only wrapper
\r
1826 /// <param name="dict">the dictionary</param>
\r
1827 public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }
\r
1831 #region IDictionary<K,V> Members
\r
1836 /// <value></value>
\r
1837 public SCG.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }
\r
1841 /// <exception cref="ReadOnlyCollectionException"> since this is a
\r
1842 /// read-only wrappper if used as a setter</exception>
\r
1843 /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
\r
1844 public V this[K key]
\r
1846 get { return dict[key]; }
\r
1847 set { throw new ReadOnlyCollectionException(); }
\r
1851 /// (This is a read-only wrapper)
\r
1853 /// <value>True</value>
\r
1854 public bool IsReadOnly { get { return true; } }
\r
1857 //TODO: guard with a read-only wrapper? Probably so!
\r
1858 /// <summary> </summary>
\r
1859 /// <value>The collection of keys of the wrapped dictionary</value>
\r
1860 public ICollectionValue<K> Keys
\r
1861 { get { return dict.Keys; } }
\r
1864 /// <summary> </summary>
\r
1865 /// <value>The collection of values of the wrapped dictionary</value>
\r
1866 public ICollectionValue<V> Values { get { return dict.Values; } }
\r
1871 public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }
\r
1875 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1876 /// <param name="key"></param>
\r
1877 /// <param name="val"></param>
\r
1878 public void Add(K key, V val)
\r
1879 { throw new ReadOnlyCollectionException(); }
\r
1884 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1885 /// <param name="items"></param>
\r
1886 public void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> items)
\r
1889 { throw new ReadOnlyCollectionException(); }
\r
1893 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1894 /// <param name="key"></param>
\r
1895 /// <returns></returns>
\r
1896 public bool Remove(K key)
\r
1897 { throw new ReadOnlyCollectionException(); }
\r
1902 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1903 /// <param name="key"></param>
\r
1904 /// <param name="val"></param>
\r
1905 /// <returns></returns>
\r
1906 public bool Remove(K key, out V val)
\r
1907 { throw new ReadOnlyCollectionException(); }
\r
1912 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1913 public void Clear()
\r
1914 { throw new ReadOnlyCollectionException(); }
\r
1919 /// <value></value>
\r
1920 public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }
\r
1923 /// Check if the wrapped dictionary contains a specific key
\r
1925 /// <param name="key">The key</param>
\r
1926 /// <returns>True if it does</returns>
\r
1927 public bool Contains(K key) { return dict.Contains(key); }
\r
1932 /// <param name="keys"></param>
\r
1933 /// <returns></returns>
\r
1934 public bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }
\r
1937 /// Search for a key in the wrapped dictionary, reporting the value if found
\r
1939 /// <param name="key">The key</param>
\r
1940 /// <param name="val">On exit: the value if found</param>
\r
1941 /// <returns>True if found</returns>
\r
1942 public bool Find(K key, out V val) { return dict.Find(key, out val); }
\r
1945 /// Search for a key in the wrapped dictionary, reporting the value if found
\r
1947 /// <param name="key">The key</param>
\r
1948 /// <param name="val">On exit: the value if found</param>
\r
1949 /// <returns>True if found</returns>
\r
1950 public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }
\r
1955 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1956 /// <param name="key"></param>
\r
1957 /// <param name="val"></param>
\r
1958 /// <returns></returns>
\r
1959 public bool Update(K key, V val)
\r
1960 { throw new ReadOnlyCollectionException(); }
\r
1965 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1966 /// <param name="key"></param>
\r
1967 /// <param name="val"></param>
\r
1968 /// <param name="oldval"></param>
\r
1969 /// <returns></returns>
\r
1970 public bool Update(K key, V val, out V oldval)
\r
1971 { throw new ReadOnlyCollectionException(); }
\r
1976 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1977 /// <param name="key"></param>
\r
1978 /// <param name="val"></param>
\r
1979 /// <returns></returns>
\r
1980 public bool FindOrAdd(K key, ref V val)
\r
1981 { throw new ReadOnlyCollectionException(); }
\r
1986 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1987 /// <param name="key"></param>
\r
1988 /// <param name="val"></param>
\r
1989 /// <returns></returns>
\r
1990 public bool UpdateOrAdd(K key, V val)
\r
1991 { throw new ReadOnlyCollectionException(); }
\r
1995 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
1996 /// <param name="key"></param>
\r
1997 /// <param name="val"></param>
\r
1998 /// <param name="oldval"></param>
\r
1999 /// <returns></returns>
\r
2000 public bool UpdateOrAdd(K key, V val, out V oldval)
\r
2001 { throw new ReadOnlyCollectionException(); }
\r
2005 /// Check the internal consistency of the wrapped dictionary
\r
2007 /// <returns>True if check passed</returns>
\r
2008 public bool Check() { return dict.Check(); }
\r
2015 /// <returns></returns>
\r
2016 public virtual object Clone()
\r
2018 return new GuardedDictionary<K, V>((IDictionary<K, V>)(dict.Clone()));
\r
2025 /// A read-only wrapper for a sorted dictionary.
\r
2027 /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>
\r
2029 public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>
\r
2033 ISortedDictionary<K, V> sorteddict;
\r
2037 #region Constructor
\r
2040 /// Wrap a sorted dictionary in a read-only wrapper
\r
2042 /// <param name="sorteddict">the dictionary</param>
\r
2043 public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)
\r
2044 : base(sorteddict)
\r
2045 { this.sorteddict = sorteddict; }
\r
2049 #region ISortedDictionary<K,V> Members
\r
2052 /// The key comparer used by this dictionary.
\r
2054 /// <value></value>
\r
2055 public SCG.IComparer<K> Comparer { get { return sorteddict.Comparer; } }
\r
2060 /// <value></value>
\r
2061 public new ISorted<K> Keys { get { return null; } }
\r
2064 /// Get the entry in the wrapped dictionary whose key is the
\r
2065 /// predecessor of a specified key.
\r
2067 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
\r
2068 /// <param name="key">The key</param>
\r
2069 /// <returns>The entry</returns>
\r
2070 public KeyValuePair<K, V> Predecessor(K key)
\r
2071 { return sorteddict.Predecessor(key); }
\r
2075 /// Get the entry in the wrapped dictionary whose key is the
\r
2076 /// successor of a specified key.
\r
2078 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
\r
2079 /// <param name="key">The key</param>
\r
2080 /// <returns>The entry</returns>
\r
2081 public KeyValuePair<K, V> Successor(K key)
\r
2082 { return sorteddict.Successor(key); }
\r
2086 /// Get the entry in the wrapped dictionary whose key is the
\r
2087 /// weak predecessor of a specified key.
\r
2089 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
\r
2090 /// <param name="key">The key</param>
\r
2091 /// <returns>The entry</returns>
\r
2092 public KeyValuePair<K, V> WeakPredecessor(K key)
\r
2093 { return sorteddict.WeakPredecessor(key); }
\r
2097 /// Get the entry in the wrapped dictionary whose key is the
\r
2098 /// weak successor of a specified key.
\r
2100 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
\r
2101 /// <param name="key">The key</param>
\r
2102 /// <returns>The entry</returns>
\r
2103 public KeyValuePair<K, V> WeakSuccessor(K key)
\r
2104 { return sorteddict.WeakSuccessor(key); }
\r
2108 #region ISortedDictionary<K,V> Members
\r
2113 /// <returns></returns>
\r
2114 public KeyValuePair<K, V> FindMin()
\r
2116 return sorteddict.FindMin();
\r
2122 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2123 /// <returns></returns>
\r
2124 public KeyValuePair<K, V> DeleteMin()
\r
2125 { throw new ReadOnlyCollectionException(); }
\r
2130 /// <returns></returns>
\r
2131 public KeyValuePair<K, V> FindMax()
\r
2133 return sorteddict.FindMax();
\r
2139 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2140 /// <returns></returns>
\r
2141 public KeyValuePair<K, V> DeleteMax()
\r
2142 { throw new ReadOnlyCollectionException(); }
\r
2147 /// <param name="c"></param>
\r
2148 /// <param name="lowEntry"></param>
\r
2149 /// <param name="lowIsValid"></param>
\r
2150 /// <param name="highEntry"></param>
\r
2151 /// <param name="highIsValid"></param>
\r
2152 /// <returns></returns>
\r
2153 public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
\r
2155 return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;
\r
2161 /// <param name="bot"></param>
\r
2162 /// <returns></returns>
\r
2163 public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
\r
2165 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));
\r
2171 /// <param name="bot"></param>
\r
2172 /// <param name="top"></param>
\r
2173 /// <returns></returns>
\r
2174 public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
\r
2176 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));
\r
2182 /// <param name="top"></param>
\r
2183 /// <returns></returns>
\r
2184 public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
\r
2186 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));
\r
2192 /// <returns></returns>
\r
2193 public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
\r
2195 return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());
\r
2201 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2202 /// <param name="items"></param>
\r
2203 public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)
\r
2204 { throw new ReadOnlyCollectionException(); }
\r
2209 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2210 /// <param name="low"></param>
\r
2211 public void RemoveRangeFrom(K low)
\r
2212 { throw new ReadOnlyCollectionException(); }
\r
2217 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2218 /// <param name="low"></param>
\r
2219 /// <param name="hi"></param>
\r
2220 public void RemoveRangeFromTo(K low, K hi)
\r
2221 { throw new ReadOnlyCollectionException(); }
\r
2226 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
\r
2227 /// <param name="hi"></param>
\r
2228 public void RemoveRangeTo(K hi)
\r
2229 { throw new ReadOnlyCollectionException(); }
\r