diff --git a/Nuclex.Support (PC).csproj b/Nuclex.Support (PC).csproj
index 71a9d57..d7bbfeb 100644
--- a/Nuclex.Support (PC).csproj
+++ b/Nuclex.Support (PC).csproj
@@ -78,6 +78,10 @@
ObservableCollection.Test
ObservableCollection.cs
+
+ false
+ PriorityItemPair
+
false
TransformingReadOnlyCollection
@@ -87,9 +91,9 @@
TransformingReadOnlyCollection.Interfaces
TransformingReadOnlyCollection.cs
-
+
false
- UnintrusivePriorityQueue
+ PairPriorityQueue
false
@@ -121,10 +125,10 @@
RingMemoryStream.Test
RingMemoryStream.cs
-
+
false
- UnintrusivePriorityQueue.Test
- UnintrusivePriorityQueue.cs
+ PairPriorityQueue.Test
+ PairPriorityQueue.cs
false
diff --git a/Source/Collections/UnintrusivePriorityQueue.Test.cs b/Source/Collections/PairPriorityQueue.Test.cs
similarity index 55%
rename from Source/Collections/UnintrusivePriorityQueue.Test.cs
rename to Source/Collections/PairPriorityQueue.Test.cs
index 148b1ab..251dd99 100644
--- a/Source/Collections/UnintrusivePriorityQueue.Test.cs
+++ b/Source/Collections/PairPriorityQueue.Test.cs
@@ -29,22 +29,22 @@ namespace Nuclex.Support.Collections {
/// Unit Test for the priority queue class
[TestFixture]
- public class UnintrusivePriorityQueueTest {
+ public class PairPriorityQueueTest {
/// Tests to ensure the count property is properly updated
[Test]
public void TestCount() {
- UnintrusivePriorityQueue testQueue =
- new UnintrusivePriorityQueue();
+ PairPriorityQueue testQueue =
+ new PairPriorityQueue();
Assert.AreEqual(0, testQueue.Count);
- testQueue.Enqueue("a", 12.34f);
+ testQueue.Enqueue(12.34f, "a");
Assert.AreEqual(1, testQueue.Count);
- testQueue.Enqueue("b", 56.78f);
+ testQueue.Enqueue(56.78f, "b");
Assert.AreEqual(2, testQueue.Count);
testQueue.Dequeue();
Assert.AreEqual(1, testQueue.Count);
- testQueue.Enqueue("c", 9.0f);
+ testQueue.Enqueue(9.0f, "c");
Assert.AreEqual(2, testQueue.Count);
testQueue.Clear();
Assert.AreEqual(0, testQueue.Count);
@@ -53,28 +53,28 @@ namespace Nuclex.Support.Collections {
/// Tests to ensure that the priority collection actually sorts items
[Test]
public void TestOrdering() {
- UnintrusivePriorityQueue testQueue =
- new UnintrusivePriorityQueue();
+ PairPriorityQueue testQueue =
+ new PairPriorityQueue();
- testQueue.Enqueue("a", 1.0f);
- testQueue.Enqueue("i", 9.0f);
- testQueue.Enqueue("b", 2.0f);
- testQueue.Enqueue("h", 8.0f);
- testQueue.Enqueue("c", 3.0f);
- testQueue.Enqueue("g", 7.0f);
- testQueue.Enqueue("d", 4.0f);
- testQueue.Enqueue("f", 6.0f);
- testQueue.Enqueue("e", 5.0f);
+ testQueue.Enqueue(1.0f, "a");
+ testQueue.Enqueue(9.0f, "i");
+ testQueue.Enqueue(2.0f, "b");
+ testQueue.Enqueue(8.0f, "h");
+ testQueue.Enqueue(3.0f, "c");
+ testQueue.Enqueue(7.0f, "g");
+ testQueue.Enqueue(4.0f, "d");
+ testQueue.Enqueue(6.0f, "f");
+ testQueue.Enqueue(5.0f, "e");
- Assert.AreEqual("i", testQueue.Dequeue());
- Assert.AreEqual("h", testQueue.Dequeue());
- Assert.AreEqual("g", testQueue.Dequeue());
- Assert.AreEqual("f", testQueue.Dequeue());
- Assert.AreEqual("e", testQueue.Dequeue());
- Assert.AreEqual("d", testQueue.Dequeue());
- Assert.AreEqual("c", testQueue.Dequeue());
- Assert.AreEqual("b", testQueue.Dequeue());
- Assert.AreEqual("a", testQueue.Dequeue());
+ Assert.AreEqual("i", testQueue.Dequeue().Item);
+ Assert.AreEqual("h", testQueue.Dequeue().Item);
+ Assert.AreEqual("g", testQueue.Dequeue().Item);
+ Assert.AreEqual("f", testQueue.Dequeue().Item);
+ Assert.AreEqual("e", testQueue.Dequeue().Item);
+ Assert.AreEqual("d", testQueue.Dequeue().Item);
+ Assert.AreEqual("c", testQueue.Dequeue().Item);
+ Assert.AreEqual("b", testQueue.Dequeue().Item);
+ Assert.AreEqual("a", testQueue.Dequeue().Item);
}
}
diff --git a/Source/Collections/PairPriorityQueue.cs b/Source/Collections/PairPriorityQueue.cs
new file mode 100644
index 0000000..dde43de
--- /dev/null
+++ b/Source/Collections/PairPriorityQueue.cs
@@ -0,0 +1,138 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2007 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+
+namespace Nuclex.Support.Collections {
+
+ /// Queue that dequeues items in order of their priority
+ ///
+ /// This variant of the priority queue uses an external priority value. If the
+ /// priority data type implements the IComparable interface, the user does not
+ /// even
+ ///
+ public class PairPriorityQueue
+ : ICollection, IEnumerable> {
+
+ #region class PairComparer
+
+ /// Compares two priority queue entries based on their priority
+ private class PairComparer : IComparer> {
+
+ /// Initializes a new entry comparer
+ /// Comparer used to compare entry priorities
+ public PairComparer(IComparer priorityComparer) {
+ this.priorityComparer = priorityComparer;
+ }
+
+ /// Compares the left entry to the right entry
+ /// Entry on the left side
+ /// Entry on the right side
+ /// The relationship of the two entries
+ public int Compare(
+ PriorityItemPair left,
+ PriorityItemPair right
+ ) {
+ return this.priorityComparer.Compare(left.Priority, right.Priority);
+ }
+
+ /// Comparer used to compare the priorities of the entries
+ private IComparer priorityComparer;
+
+ }
+
+ #endregion // class EntryComparer
+
+ /// Initializes a new non-intrusive priority queue
+ public PairPriorityQueue() : this(Comparer.Default) { }
+
+ /// Initializes a new non-intrusive priority queue
+ /// Comparer used to compare the item priorities
+ public PairPriorityQueue(IComparer priorityComparer) {
+ this.internalQueue = new PriorityQueue>(
+ new PairComparer(priorityComparer)
+ );
+ }
+
+ /// Takes the item with the highest priority off from the queue
+ /// The item with the highest priority in the list
+ public PriorityItemPair Dequeue() {
+ return this.internalQueue.Dequeue();
+ }
+
+ /// Puts an item into the priority queue
+ /// Priority of the item to be queued
+ /// Item to be queued
+ public void Enqueue(PriorityType priority, ItemType item) {
+ this.internalQueue.Enqueue(
+ new PriorityItemPair(priority, item)
+ );
+ }
+
+ /// Removes all items from the priority queue
+ public void Clear() {
+ this.internalQueue.Clear();
+ }
+
+ /// Total number of items in the priority queue
+ public int Count {
+ get { return this.internalQueue.Count; }
+ }
+
+ /// Copies the contents of the priority queue into an array
+ /// Array to copy the priority queue into
+ /// Starting index for the destination array
+ public void CopyTo(Array array, int index) {
+ this.internalQueue.CopyTo(array, index);
+ }
+
+ ///
+ /// Obtains an object that can be used to synchronize accesses to the priority queue
+ /// from different threads
+ ///
+ public object SyncRoot {
+ get { return this.internalQueue.SyncRoot; }
+ }
+
+ /// Whether operations performed on this priority queue are thread safe
+ public bool IsSynchronized {
+ get { return this.internalQueue.IsSynchronized; }
+ }
+
+ /// Returns a typesafe enumerator for the priority queue
+ /// A new enumerator for the priority queue
+ public IEnumerator> GetEnumerator() {
+ return this.internalQueue.GetEnumerator();
+ }
+
+ /// Returns an enumerator for the priority queue
+ /// A new enumerator for the priority queue
+ IEnumerator IEnumerable.GetEnumerator() {
+ return this.internalQueue.GetEnumerator();
+ }
+
+ /// Intrusive priority queue being wrapped by this class
+ private PriorityQueue> internalQueue;
+
+ }
+
+} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/PriorityItemPair.cs b/Source/Collections/PriorityItemPair.cs
new file mode 100644
index 0000000..ca8ebe8
--- /dev/null
+++ b/Source/Collections/PriorityItemPair.cs
@@ -0,0 +1,76 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2007 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Nuclex.Support.Collections {
+
+ /// An pair of a priority and an item
+ public struct PriorityItemPair {
+
+ /// Initializes a new priority / item pair
+ /// Priority of the item in the pair
+ /// Item to be stored in the pair
+ public PriorityItemPair(PriorityType priority, ItemType item) {
+ this.Priority = priority;
+ this.Item = item;
+ }
+
+ /// Priority assigned to this priority / item pair
+ public PriorityType Priority;
+ /// Item contained in this priority / item pair
+ public ItemType Item;
+
+ /// Converts the priority / item pair into a string
+ /// A string describing the priority / item pair
+ public override string ToString() {
+ int length = 4;
+
+ // Convert the priority value into a string or use the empty string
+ // constant if the ToString() overload returns null
+ string priorityString = this.Priority.ToString();
+ if(priorityString != null)
+ length += priorityString.Length;
+ else
+ priorityString = string.Empty;
+
+ // Convert the item value into a string or use the empty string
+ // constant if the ToString() overload returns null
+ string itemString = this.Item.ToString();
+ if(itemString != null)
+ length += itemString.Length;
+ else
+ itemString = string.Empty;
+
+ // Concatenate priority and item into a single string
+ StringBuilder builder = new StringBuilder(length);
+ builder.Append('[');
+ builder.Append(priorityString);
+ builder.Append(", ");
+ builder.Append(itemString);
+ builder.Append(']');
+ return builder.ToString();
+ }
+
+ }
+
+} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/PriorityQueue.cs b/Source/Collections/PriorityQueue.cs
index 1519fcd..2917492 100644
--- a/Source/Collections/PriorityQueue.cs
+++ b/Source/Collections/PriorityQueue.cs
@@ -94,6 +94,11 @@ namespace Nuclex.Support.Collections {
#endregion // class Enumerator
+ ///
+ /// Initializes a new priority queue using IComparable for comparing items
+ ///
+ public PriorityQueue() : this(Comparer.Default) { }
+
/// Initializes a new priority queue
/// Comparer to use for ordering the items
public PriorityQueue(IComparer comparer) {
diff --git a/Source/Collections/RingMemoryStream.cs b/Source/Collections/RingMemoryStream.cs
index 0d029d0..3a3b13c 100644
--- a/Source/Collections/RingMemoryStream.cs
+++ b/Source/Collections/RingMemoryStream.cs
@@ -123,8 +123,8 @@ namespace Nuclex.Support.Collections {
setEmpty();
}
- // If the end index lies before the start index, the data in the
- // ring memory stream is fragmented. Example: |#####>-------<#####|
+ // The end index lies before the start index, so the data in the
+ // ring memory stream is fragmented. Example: |#####>-------<#####|
} else {
int linearAvailable = (int)this.ringBuffer.Length - this.startIndex;
@@ -142,8 +142,8 @@ namespace Nuclex.Support.Collections {
this.startIndex = count - linearAvailable;
this.ringBuffer.Read(buffer, offset + linearAvailable, this.startIndex);
- // Nope, the amount of requested data can be read in one piece without
- // crossing the end of the ring buffer
+ // Nope, the amount of requested data can be read in one piece without
+ // crossing the end of the ring buffer
} else {
this.ringBuffer.Position = this.startIndex;
this.ringBuffer.Read(buffer, offset, count);
@@ -166,7 +166,7 @@ namespace Nuclex.Support.Collections {
public override void Write(byte[] buffer, int offset, int count) {
// The end index lies behind the start index (usual case), so the
- // ring memory is not fragmented. Example: |-----<#######>-----|
+ // unused buffer space is fragmented. Example: |-----<#######>-----|
if((this.startIndex < this.endIndex) || this.empty) {
int linearAvailable = (int)(this.ringBuffer.Length - this.endIndex);
@@ -183,8 +183,8 @@ namespace Nuclex.Support.Collections {
this.endIndex = count - linearAvailable;
this.ringBuffer.Write(buffer, offset + linearAvailable, this.endIndex);
- // All data can be appended at the current stream position without
- // crossing the ring memory stream's end
+ // All data can be appended at the current stream position without
+ // crossing the ring memory stream's end
} else {
this.ringBuffer.Position = this.endIndex;
this.ringBuffer.Write(buffer, offset, count);
@@ -193,9 +193,9 @@ namespace Nuclex.Support.Collections {
this.empty = false;
- // If the end index lies before the start index, the ring memory stream
- // has been fragmented. Hence, this means the gap into which we are about
- // to write cannot be fragmented. Example: |#####>-------<#####|
+ // The end index lies before the start index, so the data in the ring memory
+ // stream has been fragmented. This means the gap into which we are about
+ // to write is not fragmented. Example: |#####>-------<#####|
} else {
if(count > (this.startIndex - this.endIndex))
throw new OverflowException("Data does not fit in buffer");
diff --git a/Source/Collections/UnintrusivePriorityQueue.cs b/Source/Collections/UnintrusivePriorityQueue.cs
deleted file mode 100644
index ded3c61..0000000
--- a/Source/Collections/UnintrusivePriorityQueue.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-#region CPL License
-/*
-Nuclex Framework
-Copyright (C) 2002-2007 Nuclex Development Labs
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the IBM Common Public License as
-published by the IBM Corporation; either version 1.0 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-IBM Common Public License for more details.
-
-You should have received a copy of the IBM Common Public
-License along with this library
-*/
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Collections;
-
-namespace Nuclex.Support.Collections {
-
- /// Queue that dequeues items in order of their priority
- public class UnintrusivePriorityQueue
- : ICollection, IEnumerable
- where PriorityType : IComparable {
-
- #region struct Entry
-
- /// An entry in the priority queue
- private struct Entry {
-
- /// Initializes a new priority queue entry
- /// Item to be stored in the entry
- /// Priority of the item in the entry
- public Entry(ItemType item, PriorityType priority) {
- this.Item = item;
- this.Priority = priority;
- }
-
- /// Item contained in this priority queue entry
- public ItemType Item;
- /// Priority assigned to this entry
- public PriorityType Priority;
-
- }
-
- #endregion // struct Entry
-
- #region class EntryComparer
-
- /// Compares two priority queue entries based on their priority
- private class EntryComparer : IComparer {
-
- /// Compares the left entry to the right entry
- /// Entry on the left side
- /// Entry on the right side
- /// The relationship of the two entries
- public int Compare(Entry left, Entry right) {
- return left.Priority.CompareTo(right.Priority);
- }
-
- /// Default instance for this comparer
- public static readonly EntryComparer Instance = new EntryComparer();
-
- }
-
- #endregion // class EntryComparer
-
- #region class UnwrappingEnumerator
-
- /// Enumerates all items contained in a priority queue
- private class UnwrappingEnumerator : IEnumerator {
-
- /// Initializes a new priority queue enumerator
- /// Enumerator of entries to unwrap
- public UnwrappingEnumerator(IEnumerator entryEnumerator) {
- this.entryEnumerator = entryEnumerator;
- }
-
- /// Resets the enumerator to its initial state
- public void Reset() {
- this.entryEnumerator.Reset();
- }
-
- /// The current item being enumerated
- ItemType IEnumerator.Current {
- get { return this.entryEnumerator.Current.Item; }
- }
-
- /// Releases all resources used by the enumerator
- public void Dispose() {
- this.entryEnumerator.Dispose();
- }
-
- /// Moves to the next item in the priority queue
- /// True if a next item was found, false if the end has been reached
- public bool MoveNext() {
- return this.entryEnumerator.MoveNext();
- }
-
- /// The current item being enumerated
- object IEnumerator.Current {
- get { return this.entryEnumerator.Current.Item; }
- }
-
- /// Enumerator for entries to be unwrapped by this enumerator
- private IEnumerator entryEnumerator;
-
- }
-
- #endregion // class Enumerator
-
- /// Initializes a new non-intrusive priority queue
- public UnintrusivePriorityQueue() {
- this.intrusiveQueue = new PriorityQueue(EntryComparer.Instance);
- }
-
- /// Takes the item with the highest priority off from the queue
- /// The item with the highest priority in the list
- public ItemType Dequeue() {
- return this.intrusiveQueue.Dequeue().Item;
- }
-
- /// Puts an item into the priority queue
- /// Item to be queued
- /// Priority of the item to be queued
- public void Enqueue(ItemType item, PriorityType priority) {
- this.intrusiveQueue.Enqueue(new Entry(item, priority));
- }
-
- /// Removes all items from the priority queue
- public void Clear() {
- this.intrusiveQueue.Clear();
- }
-
- /// Total number of items in the priority queue
- public int Count {
- get { return this.intrusiveQueue.Count; }
- }
-
- /// Copies the contents of the priority queue into an array
- /// Array to copy the priority queue into
- /// Starting index for the destination array
- public void CopyTo(Array array, int index) {
-
- Entry[] entries = new Entry[this.intrusiveQueue.Count];
-
- this.intrusiveQueue.CopyTo(array, 0);
-
- for(int entryIndex = 0; entryIndex < this.intrusiveQueue.Count; ++entryIndex)
- array.SetValue(entries[entryIndex], entryIndex + index);
-
- }
-
- ///
- /// Obtains an object that can be used to synchronize accesses to the priority queue
- /// from different threads
- ///
- public object SyncRoot {
- get { return this.intrusiveQueue.SyncRoot; }
- }
-
- /// Whether operations performed on this priority queue are thread safe
- public bool IsSynchronized {
- get { return this.intrusiveQueue.IsSynchronized; }
- }
-
- /// Returns a typesafe enumerator for the priority queue
- /// A new enumerator for the priority queue
- public IEnumerator GetEnumerator() {
- return new UnwrappingEnumerator(this.intrusiveQueue.GetEnumerator());
- }
-
- /// Returns an enumerator for the priority queue
- /// A new enumerator for the priority queue
- IEnumerator IEnumerable.GetEnumerator() {
- return new UnwrappingEnumerator(this.intrusiveQueue.GetEnumerator());
- }
-
- /// Intrusive priority queue being wrapped by this class
- private PriorityQueue intrusiveQueue;
-
- }
-
-} // namespace Nuclex.Support.Collections