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
23 using System.Diagnostics;
24 using SCG = System.Collections.Generic;
28 /// A read-only wrapper class for a generic enumerator
30 public class GuardedEnumerator<T> : SCG.IEnumerator<T>
34 SCG.IEnumerator<T> enumerator;
41 /// Create a wrapper around a generic enumerator
43 /// <param name="enumerator">The enumerator to wrap</param>
44 public GuardedEnumerator(SCG.IEnumerator<T> enumerator)
45 { this.enumerator = enumerator; }
49 #region IEnumerator<T> Members
52 /// Move wrapped enumerator to next item, or the first item if
53 /// this is the first call to MoveNext.
55 /// <returns>True if enumerator is valid now</returns>
56 public bool MoveNext() { return enumerator.MoveNext(); }
60 /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
62 /// <value>The current item of the wrapped enumerator.</value>
63 public T Current { get { return enumerator.Current; } }
67 #region IDisposable Members
69 //TODO: consider possible danger of calling through to Dispose.
71 /// Dispose wrapped enumerator.
73 public void Dispose() { enumerator.Dispose(); }
78 #region IEnumerator Members
80 object System.Collections.IEnumerator.Current
82 get { return enumerator.Current; }
85 void System.Collections.IEnumerator.Reset()
96 /// A read-only wrapper class for a generic enumerable
98 /// <i>This is mainly interesting as a base of other guard classes</i>
100 public class GuardedEnumerable<T> : SCG.IEnumerable<T>
104 SCG.IEnumerable<T> enumerable;
111 /// Wrap an enumerable in a read-only wrapper
113 /// <param name="enumerable">The enumerable to wrap</param>
114 public GuardedEnumerable(SCG.IEnumerable<T> enumerable)
115 { this.enumerable = enumerable; }
119 #region SCG.IEnumerable<T> Members
122 /// Get an enumerator from the wrapped enumerable
124 /// <returns>The enumerator (itself wrapped)</returns>
125 public SCG.IEnumerator<T> GetEnumerator()
126 { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
130 #region IEnumerable Members
132 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
134 return GetEnumerator();
144 /// A read-only wrapper for a generic directed enumerable
146 /// <i>This is mainly interesting as a base of other guard classes</i>
148 public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>
152 IDirectedEnumerable<T> directedenumerable;
159 /// Wrap a directed enumerable in a read-only wrapper
161 /// <param name="directedenumerable">the collection to wrap</param>
162 public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
163 : base(directedenumerable)
164 { this.directedenumerable = directedenumerable; }
168 #region IDirectedEnumerable<T> Members
171 /// Get a enumerable that enumerates the wrapped collection in the opposite direction
173 /// <returns>The mirrored enumerable</returns>
174 public IDirectedEnumerable<T> Backwards()
175 { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
179 /// <code>Forwards</code> if same, else <code>Backwards</code>
181 /// <value>The enumeration direction relative to the original collection.</value>
182 public EnumerationDirection Direction
183 { get { return directedenumerable.Direction; } }
191 /// A read-only wrapper for an ICollectionValue<T>
193 /// <i>This is mainly interesting as a base of other guard classes</i>
195 public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>
199 /// The ListenableEvents value of the wrapped collection
202 public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }
205 /// The ActiveEvents value of the wrapped collection
208 public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }
210 ProxyEventBlock<T> eventBlock;
212 /// The change event. Will be raised for every change operation on the collection.
214 public event CollectionChangedHandler<T> CollectionChanged
216 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }
217 remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
221 /// The change event. Will be raised for every change operation on the collection.
223 public event CollectionClearedHandler<T> CollectionCleared
225 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }
226 remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
230 /// The item added event. Will be raised for every individual addition to the collection.
232 public event ItemsAddedHandler<T> ItemsAdded
234 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }
235 remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
239 /// The item added event. Will be raised for every individual addition to the collection.
241 public event ItemInsertedHandler<T> ItemInserted
243 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }
244 remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }
248 /// The item removed event. Will be raised for every individual removal from the collection.
250 public event ItemsRemovedHandler<T> ItemsRemoved
252 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }
253 remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
257 /// The item removed event. Will be raised for every individual removal from the collection.
259 public event ItemRemovedAtHandler<T> ItemRemovedAt
261 add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }
262 remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }
268 ICollectionValue<T> collectionvalue;
275 /// Wrap a ICollectionValue<T> in a read-only wrapper
277 /// <param name="collectionvalue">the collection to wrap</param>
278 public GuardedCollectionValue(ICollectionValue<T> collectionvalue)
279 : base(collectionvalue)
280 { this.collectionvalue = collectionvalue; }
284 #region ICollection<T> Members
287 /// Get the size of the wrapped collection
289 /// <value>The size</value>
290 public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }
293 /// Get the size of the wrapped collection
295 /// <value>The size</value>
296 public virtual int Count { get { return collectionvalue.Count; } }
299 /// The value is symbolic indicating the type of asymptotic complexity
300 /// in terms of the size of this collection (worst-case or amortized as
303 /// <value>A characterization of the speed of the
304 /// <code>Count</code> property in this collection.</value>
305 public virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
308 /// Copy the items of the wrapped collection to an array
310 /// <param name="a">The array</param>
311 /// <param name="i">Starting offset</param>
312 public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }
315 /// Create an array from the items of the wrapped collection
317 /// <returns>The array</returns>
318 public virtual T[] ToArray() { return collectionvalue.ToArray(); }
321 /// Apply a delegate to all items of the wrapped enumerable.
323 /// <param name="a">The delegate to apply</param>
324 //TODO: change this to throw an exception?
325 public virtual void Apply(Act<T> a) { collectionvalue.Apply(a); }
329 /// Check if there exists an item that satisfies a
330 /// specific predicate in the wrapped enumerable.
332 /// <param name="filter">A filter delegate
333 /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
334 /// <returns>True is such an item exists</returns>
335 public virtual bool Exists(Fun<T, bool> filter) { return collectionvalue.Exists(filter); }
340 /// <param name="filter"></param>
341 /// <param name="item"></param>
342 /// <returns></returns>
343 public virtual bool Find(Fun<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }
346 /// Check if all items in the wrapped enumerable satisfies a specific predicate.
348 /// <param name="filter">A filter delegate
349 /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
350 /// <returns>True if all items satisfies the predicate</returns>
351 public virtual bool All(Fun<T, bool> filter) { return collectionvalue.All(filter); }
354 /// Create an enumerable, enumerating the items of this collection that satisfies
355 /// a certain condition.
357 /// <param name="filter">The T->bool filter delegate defining the condition</param>
358 /// <returns>The filtered enumerable</returns>
359 public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return collectionvalue.Filter(filter); }
362 /// Choose some item of this collection.
364 /// <exception cref="NoSuchItemException">if collection is empty.</exception>
365 /// <returns></returns>
366 public virtual T Choose() { return collectionvalue.Choose(); }
370 #region IShowable Members
375 /// <param name="stringbuilder"></param>
376 /// <param name="formatProvider"></param>
377 /// <param name="rest"></param>
378 /// <returns></returns>
379 public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
381 return collectionvalue.Show(stringbuilder, ref rest, formatProvider);
385 #region IFormattable Members
390 /// <param name="format"></param>
391 /// <param name="formatProvider"></param>
392 /// <returns></returns>
393 public string ToString(string format, IFormatProvider formatProvider)
395 return collectionvalue.ToString(format, formatProvider);
404 /// A read-only wrapper for a directed collection
406 /// <i>This is mainly interesting as a base of other guard classes</i>
408 public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>
412 IDirectedCollectionValue<T> directedcollection;
419 /// Wrap a directed collection in a read-only wrapper
421 /// <param name="directedcollection">the collection to wrap</param>
422 public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)
424 base(directedcollection)
425 { this.directedcollection = directedcollection; }
429 #region IDirectedCollection<T> Members
432 /// Get a collection that enumerates the wrapped collection in the opposite direction
434 /// <returns>The mirrored collection</returns>
435 public virtual IDirectedCollectionValue<T> Backwards()
436 { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
441 /// <param name="predicate"></param>
442 /// <param name="item"></param>
443 /// <returns></returns>
444 public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }
448 #region IDirectedEnumerable<T> Members
450 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
451 { return Backwards(); }
455 /// <code>Forwards</code> if same, else <code>Backwards</code>
457 /// <value>The enumeration direction relative to the original collection.</value>
458 public EnumerationDirection Direction
459 { get { return directedcollection.Direction; } }
467 /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,
469 /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>
470 /// and <see cref="T:C5.HashBag`1"/> </i></para>
472 public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>
476 ICollection<T> collection;
483 /// Wrap an ICollection<T> in a read-only wrapper
485 /// <param name="collection">the collection to wrap</param>
486 public GuardedCollection(ICollection<T> collection)
489 this.collection = collection;
494 #region ICollection<T> Members
497 /// (This is a read-only wrapper)
499 /// <value>True</value>
500 public virtual bool IsReadOnly { get { return true; } }
503 /// <summary> </summary>
504 /// <value>Speed of wrapped collection</value>
505 public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
510 /// <returns></returns>
511 public virtual int GetUnsequencedHashCode()
512 { return collection.GetUnsequencedHashCode(); }
517 /// <param name="that"></param>
518 /// <returns></returns>
519 public virtual bool UnsequencedEquals(ICollection<T> that)
520 { return collection.UnsequencedEquals(that); }
524 /// Check if an item is in the wrapped collection
526 /// <param name="item">The item</param>
527 /// <returns>True if found</returns>
528 public virtual bool Contains(T item) { return collection.Contains(item); }
532 /// Count the number of times an item appears in the wrapped collection
534 /// <param name="item">The item</param>
535 /// <returns>The number of copies</returns>
536 public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }
541 /// <returns></returns>
542 public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }
547 /// <returns></returns>
548 public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }
551 /// Check if all items in the argument is in the wrapped collection
553 /// <param name="items">The items</param>
554 /// <typeparam name="U"></typeparam>
555 /// <returns>True if so</returns>
556 public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T { return collection.ContainsAll(items); }
559 /// Search for an item in the wrapped collection
561 /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
562 /// <returns></returns>
563 public virtual bool Find(ref T item) { return collection.Find(ref item); }
568 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
569 /// <param name="item"></param>
570 /// <returns></returns>
571 public virtual bool FindOrAdd(ref T item)
572 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
577 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
578 /// <param name="item"></param>
579 /// <returns></returns>
580 public virtual bool Update(T item)
581 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
586 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
587 /// <param name="item"></param>
588 /// <param name="olditem"></param>
589 /// <returns></returns>
590 public virtual bool Update(T item, out T olditem)
591 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
596 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
597 /// <param name="item"></param>
598 /// <returns></returns>
599 public virtual bool UpdateOrAdd(T item)
600 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
605 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
606 /// <param name="item"></param>
607 /// <param name="olditem"></param>
608 /// <returns></returns>
609 public virtual bool UpdateOrAdd(T item, out T olditem)
610 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
614 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
615 /// <param name="item"></param>
616 /// <returns></returns>
617 public virtual bool Remove(T item)
618 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
623 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
624 /// <param name="item">The value to remove.</param>
625 /// <param name="removeditem">The removed value.</param>
626 /// <returns></returns>
627 public virtual bool Remove(T item, out T removeditem)
628 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
633 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
634 /// <param name="item"></param>
635 public virtual void RemoveAllCopies(T item)
636 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
641 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
642 /// <typeparam name="U"></typeparam>
643 /// <param name="items"></param>
644 public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
645 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
649 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
650 public virtual void Clear()
651 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
656 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
657 /// <typeparam name="U"></typeparam>
658 /// <param name="items"></param>
659 public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
660 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
663 /// Check wrapped collection for internal consistency
665 /// <returns>True if check passed</returns>
666 public virtual bool Check() { return collection.Check(); }
670 #region IExtensible<T> Members
672 /// <summary> </summary>
673 /// <value>False if wrapped collection has set semantics</value>
674 public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
676 //TODO: the equalityComparer should be guarded
681 public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }
684 /// By convention this is true for any collection with set semantics.
686 /// <value>True if only one representative of a group of equal items
687 /// is kept in the collection together with the total count.</value>
688 public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }
691 /// <summary> </summary>
692 /// <value>True if wrapped collection is empty</value>
693 public override bool IsEmpty { get { return collection.IsEmpty; } }
698 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
699 /// <param name="item"></param>
700 /// <returns></returns>
701 public virtual bool Add(T item)
702 { throw new ReadOnlyCollectionException(); }
706 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
707 /// <param name="item"></param>
708 void SCG.ICollection<T>.Add(T item)
709 { throw new ReadOnlyCollectionException(); }
713 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
714 /// <typeparam name="U"></typeparam>
715 /// <param name="items"></param>
716 public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
717 { throw new ReadOnlyCollectionException(); }
721 #region ICloneable Members
726 /// <returns></returns>
727 public virtual object Clone()
729 return new GuardedCollection<T>((ICollection<T>)(collection.Clone()));
738 /// A read-only wrapper for a sequenced collection
740 /// <i>This is mainly interesting as a base of other guard classes</i>
742 public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>
746 ISequenced<T> sequenced;
753 /// Wrap a sequenced collection in a read-only wrapper
755 /// <param name="sorted"></param>
756 public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }
761 /// Check if there exists an item that satisfies a
762 /// specific predicate in this collection and return the index of the first one.
764 /// <param name="predicate">A delegate
765 /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
766 /// <returns>the index, if found, a negative value else</returns>
767 public int FindIndex(Fun<T, bool> predicate)
769 IIndexed<T> indexed = sequenced as IIndexed<T>;
771 return indexed.FindIndex(predicate);
773 foreach (T item in this)
783 /// Check if there exists an item that satisfies a
784 /// specific predicate in this collection and return the index of the last one.
786 /// <param name="predicate">A delegate
787 /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
788 /// <returns>the index, if found, a negative value else</returns>
789 public int FindLastIndex(Fun<T, bool> predicate)
791 IIndexed<T> indexed = sequenced as IIndexed<T>;
793 return indexed.FindLastIndex(predicate);
794 int index = Count - 1;
795 foreach (T item in Backwards())
806 #region ISequenced<T> Members
811 /// <returns></returns>
812 public int GetSequencedHashCode()
813 { return sequenced.GetSequencedHashCode(); }
818 /// <param name="that"></param>
819 /// <returns></returns>
820 public bool SequencedEquals(ISequenced<T> that)
821 { return sequenced.SequencedEquals(that); }
825 #region IDirectedCollection<T> Members
828 /// Get a collection that enumerates the wrapped collection in the opposite direction
830 /// <returns>The mirrored collection</returns>
831 public virtual IDirectedCollectionValue<T> Backwards()
832 { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
837 /// <param name="predicate"></param>
838 /// <param name="item"></param>
839 /// <returns></returns>
840 public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }
844 #region IDirectedEnumerable<T> Members
846 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
847 { return Backwards(); }
852 /// <code>Forwards</code> if same, else <code>Backwards</code>
854 /// <value>The enumeration direction relative to the original collection.</value>
855 public EnumerationDirection Direction
856 { get { return EnumerationDirection.Forwards; } }
860 #region ICloneable Members
865 /// <returns></returns>
866 public override object Clone()
868 return new GuardedCollection<T>((ISequenced<T>)(sequenced.Clone()));
877 /// A read-only wrapper for a sorted collection
879 /// <i>This is mainly interesting as a base of other guard classes</i>
881 public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>
892 /// Wrap a sorted collection in a read-only wrapper
894 /// <param name="sorted"></param>
895 public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }
899 #region ISorted<T> Members
902 /// Find the strict predecessor of item in the guarded sorted collection,
903 /// that is, the greatest item in the collection smaller than the item.
905 /// <param name="item">The item to find the predecessor for.</param>
906 /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
907 /// <returns>True if item has a predecessor; otherwise false.</returns>
908 public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); }
912 /// Find the strict successor of item in the guarded sorted collection,
913 /// that is, the least item in the collection greater than the supplied value.
915 /// <param name="item">The item to find the successor for.</param>
916 /// <param name="res">The successor, if any; otherwise the default value for T.</param>
917 /// <returns>True if item has a successor; otherwise false.</returns>
918 public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); }
922 /// Find the weak predecessor of item in the guarded sorted collection,
923 /// that is, the greatest item in the collection smaller than or equal to the item.
925 /// <param name="item">The item to find the weak predecessor for.</param>
926 /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
927 /// <returns>True if item has a weak predecessor; otherwise false.</returns>
928 public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); }
932 /// Find the weak successor of item in the sorted collection,
933 /// that is, the least item in the collection greater than or equal to the supplied value.
935 /// <param name="item">The item to find the weak successor for.</param>
936 /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
937 /// <returns>True if item has a weak successor; otherwise false.</returns>
938 public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); }
942 /// Find the predecessor of the item in the wrapped sorted collection
944 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
945 /// <param name="item">The item</param>
946 /// <returns>The predecessor</returns>
947 public T Predecessor(T item) { return sorted.Predecessor(item); }
951 /// Find the Successor of the item in the wrapped sorted collection
953 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
954 /// <param name="item">The item</param>
955 /// <returns>The Successor</returns>
956 public T Successor(T item) { return sorted.Successor(item); }
960 /// Find the weak predecessor of the item in the wrapped sorted collection
962 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
963 /// <param name="item">The item</param>
964 /// <returns>The weak predecessor</returns>
965 public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
969 /// Find the weak Successor of the item in the wrapped sorted collection
971 /// <exception cref="NoSuchItemException"> if no such element exists </exception>
972 /// <param name="item">The item</param>
973 /// <returns>The weak Successor</returns>
974 public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
978 /// Run Cut on the wrapped sorted collection
980 /// <param name="c"></param>
981 /// <param name="low"></param>
982 /// <param name="lval"></param>
983 /// <param name="high"></param>
984 /// <param name="hval"></param>
985 /// <returns></returns>
986 public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
987 { return sorted.Cut(c, out low, out lval, out high, out hval); }
991 /// Get the specified range from the wrapped collection.
992 /// (The current implementation erroneously does not wrap the result.)
994 /// <param name="bot"></param>
995 /// <returns></returns>
996 public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
1000 /// Get the specified range from the wrapped collection.
1001 /// (The current implementation erroneously does not wrap the result.)
1003 /// <param name="bot"></param>
1004 /// <param name="top"></param>
1005 /// <returns></returns>
1006 public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
1007 { return sorted.RangeFromTo(bot, top); }
1011 /// Get the specified range from the wrapped collection.
1012 /// (The current implementation erroneously does not wrap the result.)
1014 /// <param name="top"></param>
1015 /// <returns></returns>
1016 public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
1020 /// Get the specified range from the wrapped collection.
1021 /// (The current implementation erroneously does not wrap the result.)
1023 /// <returns></returns>
1024 public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
1028 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1029 /// <param name="items"></param>
1030 /// <typeparam name="U"></typeparam>
1031 public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
1032 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1036 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1037 /// <param name="low"></param>
1038 public void RemoveRangeFrom(T low)
1039 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1044 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1045 /// <param name="low"></param>
1046 /// <param name="hi"></param>
1047 public void RemoveRangeFromTo(T low, T hi)
1048 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1053 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1054 /// <param name="hi"></param>
1055 public void RemoveRangeTo(T hi)
1056 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1060 #region IPriorityQueue<T> Members
1063 /// Find the minimum of the wrapped collection
1065 /// <returns>The minimum</returns>
1066 public T FindMin() { return sorted.FindMin(); }
1071 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1072 /// <returns></returns>
1073 public T DeleteMin()
1074 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1078 /// Find the maximum of the wrapped collection
1080 /// <returns>The maximum</returns>
1081 public T FindMax() { return sorted.FindMax(); }
1086 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1087 /// <returns></returns>
1088 public T DeleteMax()
1089 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1091 //TODO: we should guard the comparer!
1093 /// The comparer object supplied at creation time for the underlying collection
1095 /// <value>The comparer</value>
1096 public SCG.IComparer<T> Comparer { get { return sorted.Comparer; } }
1099 #region IDirectedEnumerable<T> Members
1101 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1102 { return Backwards(); }
1109 /// <returns></returns>
1110 public override object Clone()
1112 return new GuardedSorted<T>((ISorted<T>)(sorted.Clone()));
1120 /// Read-only wrapper for indexed sorted collections
1122 /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>
1124 public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>
1128 IIndexedSorted<T> indexedsorted;
1135 /// Wrap an indexed sorted collection in a read-only wrapper
1137 /// <param name="list">the indexed sorted collection</param>
1138 public GuardedIndexedSorted(IIndexedSorted<T> list)
1140 { this.indexedsorted = list; }
1144 #region IIndexedSorted<T> Members
1147 /// Get the specified range from the wrapped collection.
1148 /// (The current implementation erroneously does not wrap the result.)
1150 /// <param name="bot"></param>
1151 /// <returns></returns>
1152 public new IDirectedCollectionValue<T> RangeFrom(T bot)
1153 { return indexedsorted.RangeFrom(bot); }
1157 /// Get the specified range from the wrapped collection.
1158 /// (The current implementation erroneously does not wrap the result.)
1160 /// <param name="bot"></param>
1161 /// <param name="top"></param>
1162 /// <returns></returns>
1163 public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
1164 { return indexedsorted.RangeFromTo(bot, top); }
1168 /// Get the specified range from the wrapped collection.
1169 /// (The current implementation erroneously does not wrap the result.)
1171 /// <param name="top"></param>
1172 /// <returns></returns>
1173 public new IDirectedCollectionValue<T> RangeTo(T top)
1174 { return indexedsorted.RangeTo(top); }
1178 /// Report the number of items in the specified range of the wrapped collection
1180 /// <param name="bot"></param>
1181 /// <returns></returns>
1182 public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
1186 /// Report the number of items in the specified range of the wrapped collection
1188 /// <param name="bot"></param>
1189 /// <param name="top"></param>
1190 /// <returns></returns>
1191 public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
1195 /// Report the number of items in the specified range of the wrapped collection
1197 /// <param name="top"></param>
1198 /// <returns></returns>
1199 public int CountTo(T top) { return indexedsorted.CountTo(top); }
1203 /// Run FindAll on the wrapped collection with the indicated filter.
1204 /// The result will <b>not</b> be read-only.
1206 /// <param name="f"></param>
1207 /// <returns></returns>
1208 public IIndexedSorted<T> FindAll(Fun<T, bool> f)
1209 { return indexedsorted.FindAll(f); }
1213 /// Run Map on the wrapped collection with the indicated mapper.
1214 /// The result will <b>not</b> be read-only.
1216 /// <param name="m"></param>
1217 /// <param name="c">The comparer to use in the result</param>
1218 /// <returns></returns>
1219 public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)
1220 { return indexedsorted.Map(m, c); }
1224 #region IIndexed<T> Members
1229 /// <value>The i'th item of the wrapped sorted collection</value>
1230 public T this[int i] { get { return indexedsorted[i]; } }
1236 public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }
1238 /// <summary> </summary>
1239 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
1240 public IDirectedCollectionValue<T> this[int start, int end]
1241 { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
1245 /// Find the (first) index of an item in the wrapped collection
1247 /// <param name="item"></param>
1248 /// <returns></returns>
1249 public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
1253 /// Find the last index of an item in the wrapped collection
1255 /// <param name="item"></param>
1256 /// <returns></returns>
1257 public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
1262 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1263 /// <param name="i"></param>
1264 /// <returns></returns>
1265 public T RemoveAt(int i)
1266 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1271 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1272 /// <param name="start"></param>
1273 /// <param name="count"></param>
1274 public void RemoveInterval(int start, int count)
1275 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1279 #region IDirectedEnumerable<T> Members
1281 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1282 { return Backwards(); }
1289 /// <returns></returns>
1290 public override object Clone()
1292 return new GuardedIndexedSorted<T>((IIndexedSorted<T>)(indexedsorted.Clone()));
1300 /// A read-only wrapper for a generic list collection
1301 /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
1302 /// <see cref="T:C5.LinkedList`1"/>,
1303 /// <see cref="T:C5.HashedLinkedList`1"/>,
1304 /// <see cref="T:C5.ArrayList`1"/> or
1305 /// <see cref="T:C5.HashedArray`1"/>.
1308 public class GuardedList<T> : GuardedSequenced<T>, IList<T>, SCG.IList<T>
1313 GuardedList<T> underlying;
1314 bool slidableView = false;
1321 /// Wrap a list in a read-only wrapper. A list gets wrapped as read-only,
1322 /// a list view gets wrapped as read-only and non-slidable.
1324 /// <param name="list">The list</param>
1325 public GuardedList(IList<T> list)
1328 this.innerlist = list;
1329 // If wrapping a list view, make innerlist = the view, and make
1330 // underlying = a guarded version of the view's underlying list
1331 if (list.Underlying != null)
1332 underlying = new GuardedList<T>(list.Underlying, null, false);
1335 GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)
1338 this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;
1342 #region IList<T> Members
1347 /// <value>The first item of the wrapped list</value>
1348 public T First { get { return innerlist.First; } }
1354 /// <value>The last item of the wrapped list</value>
1355 public T Last { get { return innerlist.Last; } }
1360 /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
1361 /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
1364 get { return innerlist.FIFO; }
1365 set { throw new ReadOnlyCollectionException("List is read only"); }
1371 public virtual bool IsFixedSize
1373 get { return true; }
1379 /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
1380 /// <value>The i'th item of the wrapped list</value>
1381 public T this[int i]
1383 get { return innerlist[i]; }
1384 set { throw new ReadOnlyCollectionException("List is read only"); }
1391 public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }
1395 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1396 /// <param name="index"></param>
1397 /// <param name="item"></param>
1398 public void Insert(int index, T item)
1399 { throw new ReadOnlyCollectionException(); }
1403 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1404 /// <param name="pointer"></param>
1405 /// <param name="item"></param>
1406 public void Insert(IList<T> pointer, T item)
1407 { throw new ReadOnlyCollectionException(); }
1411 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1412 /// <param name="item"></param>
1413 public void InsertFirst(T item)
1414 { throw new ReadOnlyCollectionException("List is read only"); }
1418 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1419 /// <param name="item"></param>
1420 public void InsertLast(T item)
1421 { throw new ReadOnlyCollectionException("List is read only"); }
1425 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1426 /// <param name="item"></param>
1427 /// <param name="target"></param>
1428 public void InsertBefore(T item, T target)
1429 { throw new ReadOnlyCollectionException("List is read only"); }
1434 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1435 /// <param name="item"></param>
1436 /// <param name="target"></param>
1437 public void InsertAfter(T item, T target)
1438 { throw new ReadOnlyCollectionException("List is read only"); }
1443 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1444 /// <param name="i"></param>
1445 /// <param name="items"></param>
1446 public void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
1447 { throw new ReadOnlyCollectionException("List is read only"); }
1451 /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
1453 /// <param name="filter">The filter to use</param>
1454 /// <returns></returns>
1455 public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
1459 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1461 /// <typeparam name="V">The type of items of the new list</typeparam>
1462 /// <param name="mapper">The mapper to use.</param>
1463 /// <returns>The mapped list</returns>
1464 public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map(mapper); }
1467 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1469 /// <typeparam name="V">The type of items of the new list</typeparam>
1470 /// <param name="mapper">The delegate defining the map.</param>
1471 /// <param name="itemequalityComparer">The itemequalityComparer to use for the new list</param>
1472 /// <returns>The new list.</returns>
1473 public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }
1477 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1478 /// <returns></returns>
1479 public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }
1484 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1485 /// <returns></returns>
1486 public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }
1491 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1492 /// <returns></returns>
1493 public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }
1497 /// Create the indicated view on the wrapped list and wrap it read-only.
1499 /// <param name="start"></param>
1500 /// <param name="count"></param>
1501 /// <returns></returns>
1502 public IList<T> View(int start, int count)
1504 IList<T> view = innerlist.View(start, count);
1505 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1509 /// Create the indicated view on the wrapped list and wrap it read-only.
1511 /// <param name="item"></param>
1512 /// <returns></returns>
1513 public IList<T> ViewOf(T item)
1515 IList<T> view = innerlist.ViewOf(item);
1516 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1520 /// Create the indicated view on the wrapped list and wrap it read-only.
1522 /// <param name="item"></param>
1523 /// <returns></returns>
1524 public IList<T> LastViewOf(T item)
1526 IList<T> view = innerlist.LastViewOf(item);
1527 return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1533 /// <value>The wrapped underlying list of the wrapped view </value>
1534 public IList<T> Underlying { get { return underlying; } }
1540 /// <value>The offset of the wrapped list as a view.</value>
1541 public int Offset { get { return innerlist.Offset; } }
1547 public virtual bool IsValid { get { return innerlist.IsValid; } }
1551 /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>
1552 /// <param name="offset"></param>
1553 public IList<T> Slide(int offset)
1557 innerlist.Slide(offset);
1561 throw new ReadOnlyCollectionException("List is read only");
1567 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1568 /// <param name="offset"></param>
1569 /// <param name="size"></param>
1570 public IList<T> Slide(int offset, int size)
1574 innerlist.Slide(offset, size);
1578 throw new ReadOnlyCollectionException("List is read only");
1585 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1586 /// <param name="offset"></param>
1587 /// <returns></returns>
1588 public bool TrySlide(int offset)
1591 return innerlist.TrySlide(offset);
1593 throw new ReadOnlyCollectionException("List is read only");
1599 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1600 /// <param name="offset"></param>
1601 /// <param name="size"></param>
1602 /// <returns></returns>
1603 public bool TrySlide(int offset, int size)
1606 return innerlist.TrySlide(offset, size);
1608 throw new ReadOnlyCollectionException("List is read only");
1614 /// <param name="otherView"></param>
1615 /// <returns></returns>
1616 public IList<T> Span(IList<T> otherView)
1618 GuardedList<T> otherGuardedList = otherView as GuardedList<T>;
1619 if (otherGuardedList == null)
1620 throw new IncompatibleViewException();
1621 IList<T> span = innerlist.Span(otherGuardedList.innerlist);
1624 return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);
1628 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1630 public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }
1635 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1636 /// <param name="start"></param>
1637 /// <param name="count"></param>
1638 public void Reverse(int start, int count)
1639 { throw new ReadOnlyCollectionException("List is read only"); }
1643 /// Check if wrapped list is sorted according to the default sorting order
1644 /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class
1646 /// <exception cref="NotComparableException">if T is not comparable</exception>
1647 /// <returns>True if the list is sorted, else false.</returns>
1648 public bool IsSorted() { return innerlist.IsSorted(Comparer<T>.Default); }
1651 /// Check if wrapped list is sorted
1653 /// <param name="c">The sorting order to use</param>
1654 /// <returns>True if sorted</returns>
1655 public bool IsSorted(SCG.IComparer<T> c) { return innerlist.IsSorted(c); }
1660 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1662 { throw new ReadOnlyCollectionException("List is read only"); }
1667 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1668 /// <param name="c"></param>
1669 public void Sort(SCG.IComparer<T> c)
1670 { throw new ReadOnlyCollectionException("List is read only"); }
1674 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1675 public void Shuffle()
1676 { throw new ReadOnlyCollectionException("List is read only"); }
1681 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1682 /// <param name="rnd"></param>
1683 public void Shuffle(Random rnd)
1684 { throw new ReadOnlyCollectionException("List is read only"); }
1688 #region IIndexed<T> Members
1690 /// <summary> </summary>
1691 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
1692 public IDirectedCollectionValue<T> this[int start, int end]
1693 { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }
1697 /// Find the (first) index of an item in the wrapped collection
1699 /// <param name="item"></param>
1700 /// <returns></returns>
1701 public int IndexOf(T item) { return innerlist.IndexOf(item); }
1705 /// Find the last index of an item in the wrapped collection
1707 /// <param name="item"></param>
1708 /// <returns></returns>
1709 public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
1714 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1715 /// <param name="i"></param>
1716 /// <returns></returns>
1717 public T RemoveAt(int i)
1718 { throw new ReadOnlyCollectionException("List is read only"); }
1723 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1724 /// <param name="start"></param>
1725 /// <param name="count"></param>
1726 public void RemoveInterval(int start, int count)
1727 { throw new ReadOnlyCollectionException("List is read only"); }
1731 #region IDirectedEnumerable<T> Members
1733 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1734 { return Backwards(); }
1738 #region IStack<T> Members
1744 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1745 /// <returns>-</returns>
1746 public void Push(T item)
1747 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1752 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1753 /// <returns>-</returns>
1755 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1759 #region IQueue<T> Members
1764 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1765 /// <returns>-</returns>
1766 public void Enqueue(T item)
1767 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1772 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1773 /// <returns>-</returns>
1775 { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1779 #region IDisposable Members
1782 /// Ignore: this may be called by a foreach or using statement.
1784 public void Dispose() { }
1791 /// <returns></returns>
1792 public override object Clone()
1794 return new GuardedList<T>((IList<T>)(innerlist.Clone()));
1797 #region System.Collections.Generic.IList<T> Members
1799 void System.Collections.Generic.IList<T>.RemoveAt(int index)
1801 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1804 void System.Collections.Generic.ICollection<T>.Add(T item)
1806 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1811 #region System.Collections.ICollection Members
1813 bool System.Collections.ICollection.IsSynchronized
1815 get { return false; }
1819 Object System.Collections.ICollection.SyncRoot
1821 get { return innerlist.SyncRoot; }
1824 void System.Collections.ICollection.CopyTo(Array arr, int index)
1826 if (index < 0 || index + Count > arr.Length)
1827 throw new ArgumentOutOfRangeException();
1829 foreach (T item in this)
1830 arr.SetValue(item, index++);
1835 #region System.Collections.IList Members
1837 Object System.Collections.IList.this[int index]
1839 get { return this[index]; }
1842 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1846 int System.Collections.IList.Add(Object o)
1848 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1851 bool System.Collections.IList.Contains(Object o)
1853 return Contains((T)o);
1856 int System.Collections.IList.IndexOf(Object o)
1858 return Math.Max(-1, IndexOf((T)o));
1861 void System.Collections.IList.Insert(int index, Object o)
1863 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1866 void System.Collections.IList.Remove(Object o)
1868 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1871 void System.Collections.IList.RemoveAt(int index)
1873 throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1880 /// A read-only wrapper for a generic indexable queue (allows indexing).
1882 /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>
1884 /// <typeparam name="T">The item type.</typeparam>
1885 public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>
1896 /// Wrap a queue in a read-only wrapper
1898 /// <param name="queue">The queue</param>
1899 public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }
1903 #region IQueue<T> Members
1908 public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }
1911 /// Index into the wrapped queue
1913 /// <param name="i"></param>
1914 /// <returns></returns>
1915 public T this[int i] { get { return queue[i]; } }
1920 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1921 /// <returns>-</returns>
1922 public void Enqueue(T item)
1923 { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
1928 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1929 /// <returns>-</returns>
1931 { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
1937 /// A read-only wrapper for a dictionary.
1939 /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>
1941 public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>
1945 IDictionary<K, V> dict;
1952 /// Wrap a dictionary in a read-only wrapper
1954 /// <param name="dict">the dictionary</param>
1955 public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }
1959 #region IDictionary<K,V> Members
1965 public SCG.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }
1969 /// <exception cref="ReadOnlyCollectionException"> since this is a
1970 /// read-only wrappper if used as a setter</exception>
1971 /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
1972 public V this[K key]
1974 get { return dict[key]; }
1975 set { throw new ReadOnlyCollectionException(); }
1979 /// (This is a read-only wrapper)
1981 /// <value>True</value>
1982 public bool IsReadOnly { get { return true; } }
1985 //TODO: guard with a read-only wrapper? Probably so!
1986 /// <summary> </summary>
1987 /// <value>The collection of keys of the wrapped dictionary</value>
1988 public ICollectionValue<K> Keys
1989 { get { return dict.Keys; } }
1992 /// <summary> </summary>
1993 /// <value>The collection of values of the wrapped dictionary</value>
1994 public ICollectionValue<V> Values { get { return dict.Values; } }
1999 public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }
2003 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2004 /// <param name="key"></param>
2005 /// <param name="val"></param>
2006 public void Add(K key, V val)
2007 { throw new ReadOnlyCollectionException(); }
2012 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2013 /// <param name="items"></param>
2014 public void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> items)
2017 { throw new ReadOnlyCollectionException(); }
2021 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2022 /// <param name="key"></param>
2023 /// <returns></returns>
2024 public bool Remove(K key)
2025 { throw new ReadOnlyCollectionException(); }
2030 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2031 /// <param name="key"></param>
2032 /// <param name="val"></param>
2033 /// <returns></returns>
2034 public bool Remove(K key, out V val)
2035 { throw new ReadOnlyCollectionException(); }
2040 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2042 { throw new ReadOnlyCollectionException(); }
2048 public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }
2051 /// Check if the wrapped dictionary contains a specific key
2053 /// <param name="key">The key</param>
2054 /// <returns>True if it does</returns>
2055 public bool Contains(K key) { return dict.Contains(key); }
2060 /// <param name="keys"></param>
2061 /// <returns></returns>
2062 public bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }
2065 /// Search for a key in the wrapped dictionary, reporting the value if found
2067 /// <param name="key">The key</param>
2068 /// <param name="val">On exit: the value if found</param>
2069 /// <returns>True if found</returns>
2070 public bool Find(K key, out V val) { return dict.Find(key, out val); }
2073 /// Search for a key in the wrapped dictionary, reporting the value if found
2075 /// <param name="key">The key</param>
2076 /// <param name="val">On exit: the value if found</param>
2077 /// <returns>True if found</returns>
2078 public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }
2083 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2084 /// <param name="key"></param>
2085 /// <param name="val"></param>
2086 /// <returns></returns>
2087 public bool Update(K key, V val)
2088 { throw new ReadOnlyCollectionException(); }
2093 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2094 /// <param name="key"></param>
2095 /// <param name="val"></param>
2096 /// <param name="oldval"></param>
2097 /// <returns></returns>
2098 public bool Update(K key, V val, out V oldval)
2099 { throw new ReadOnlyCollectionException(); }
2104 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2105 /// <param name="key"></param>
2106 /// <param name="val"></param>
2107 /// <returns></returns>
2108 public bool FindOrAdd(K key, ref V val)
2109 { throw new ReadOnlyCollectionException(); }
2114 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2115 /// <param name="key"></param>
2116 /// <param name="val"></param>
2117 /// <returns></returns>
2118 public bool UpdateOrAdd(K key, V val)
2119 { throw new ReadOnlyCollectionException(); }
2123 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2124 /// <param name="key"></param>
2125 /// <param name="val"></param>
2126 /// <param name="oldval"></param>
2127 /// <returns></returns>
2128 public bool UpdateOrAdd(K key, V val, out V oldval)
2129 { throw new ReadOnlyCollectionException(); }
2133 /// Check the internal consistency of the wrapped dictionary
2135 /// <returns>True if check passed</returns>
2136 public bool Check() { return dict.Check(); }
2143 /// <returns></returns>
2144 public virtual object Clone()
2146 return new GuardedDictionary<K, V>((IDictionary<K, V>)(dict.Clone()));
2153 /// A read-only wrapper for a sorted dictionary.
2155 /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>
2157 public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>
2161 ISortedDictionary<K, V> sorteddict;
2168 /// Wrap a sorted dictionary in a read-only wrapper
2170 /// <param name="sorteddict">the dictionary</param>
2171 public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)
2173 { this.sorteddict = sorteddict; }
2177 #region ISortedDictionary<K,V> Members
2180 /// The key comparer used by this dictionary.
2183 public SCG.IComparer<K> Comparer { get { return sorteddict.Comparer; } }
2189 public new ISorted<K> Keys { get { return null; } }
2192 /// Find the entry in the dictionary whose key is the
2193 /// predecessor of the specified key.
2195 /// <param name="key">The key</param>
2196 /// <param name="res">The predecessor, if any</param>
2197 /// <returns>True if key has a predecessor</returns>
2198 public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
2200 return sorteddict.TryPredecessor(key, out res);
2204 /// Find the entry in the dictionary whose key is the
2205 /// successor of the specified key.
2207 /// <param name="key">The key</param>
2208 /// <param name="res">The successor, if any</param>
2209 /// <returns>True if the key has a successor</returns>
2210 public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
2212 return sorteddict.TrySuccessor(key, out res);
2216 /// Find the entry in the dictionary whose key is the
2217 /// weak predecessor of the specified key.
2219 /// <param name="key">The key</param>
2220 /// <param name="res">The predecessor, if any</param>
2221 /// <returns>True if key has a weak predecessor</returns>
2222 public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
2224 return sorteddict.TryWeakPredecessor(key, out res);
2228 /// Find the entry in the dictionary whose key is the
2229 /// weak successor of the specified key.
2231 /// <param name="key">The key</param>
2232 /// <param name="res">The weak successor, if any</param>
2233 /// <returns>True if the key has a weak successor</returns>
2234 public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
2236 return sorteddict.TryWeakSuccessor(key, out res);
2240 /// Get the entry in the wrapped dictionary whose key is the
2241 /// predecessor of a specified key.
2243 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
2244 /// <param name="key">The key</param>
2245 /// <returns>The entry</returns>
2246 public KeyValuePair<K, V> Predecessor(K key)
2247 { return sorteddict.Predecessor(key); }
2250 /// Get the entry in the wrapped dictionary whose key is the
2251 /// successor of a specified key.
2253 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
2254 /// <param name="key">The key</param>
2255 /// <returns>The entry</returns>
2256 public KeyValuePair<K, V> Successor(K key)
2257 { return sorteddict.Successor(key); }
2261 /// Get the entry in the wrapped dictionary whose key is the
2262 /// weak predecessor of a specified key.
2264 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
2265 /// <param name="key">The key</param>
2266 /// <returns>The entry</returns>
2267 public KeyValuePair<K, V> WeakPredecessor(K key)
2268 { return sorteddict.WeakPredecessor(key); }
2272 /// Get the entry in the wrapped dictionary whose key is the
2273 /// weak successor of a specified key.
2275 /// <exception cref="NoSuchItemException"> if no such entry exists </exception>
2276 /// <param name="key">The key</param>
2277 /// <returns>The entry</returns>
2278 public KeyValuePair<K, V> WeakSuccessor(K key)
2279 { return sorteddict.WeakSuccessor(key); }
2284 /// <returns></returns>
2285 public KeyValuePair<K, V> FindMin()
2287 return sorteddict.FindMin();
2293 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2294 /// <returns></returns>
2295 public KeyValuePair<K, V> DeleteMin()
2296 { throw new ReadOnlyCollectionException(); }
2301 /// <returns></returns>
2302 public KeyValuePair<K, V> FindMax()
2304 return sorteddict.FindMax();
2310 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2311 /// <returns></returns>
2312 public KeyValuePair<K, V> DeleteMax()
2313 { throw new ReadOnlyCollectionException(); }
2318 /// <param name="c"></param>
2319 /// <param name="lowEntry"></param>
2320 /// <param name="lowIsValid"></param>
2321 /// <param name="highEntry"></param>
2322 /// <param name="highIsValid"></param>
2323 /// <returns></returns>
2324 public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
2326 return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;
2332 /// <param name="bot"></param>
2333 /// <returns></returns>
2334 public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
2336 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));
2342 /// <param name="bot"></param>
2343 /// <param name="top"></param>
2344 /// <returns></returns>
2345 public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
2347 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));
2353 /// <param name="top"></param>
2354 /// <returns></returns>
2355 public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
2357 return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));
2363 /// <returns></returns>
2364 public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
2366 return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());
2372 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2373 /// <param name="items"></param>
2374 public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)
2375 { throw new ReadOnlyCollectionException(); }
2380 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2381 /// <param name="low"></param>
2382 public void RemoveRangeFrom(K low)
2383 { throw new ReadOnlyCollectionException(); }
2388 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2389 /// <param name="low"></param>
2390 /// <param name="hi"></param>
2391 public void RemoveRangeFromTo(K low, K hi)
2392 { throw new ReadOnlyCollectionException(); }
2397 /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2398 /// <param name="hi"></param>
2399 public void RemoveRangeTo(K hi)
2400 { throw new ReadOnlyCollectionException(); }