diff --git a/Source/Collections/ParentingCollection.cs b/Source/Collections/ParentingCollection.cs
index 2745762..9fe4e65 100644
--- a/Source/Collections/ParentingCollection.cs
+++ b/Source/Collections/ParentingCollection.cs
@@ -95,7 +95,7 @@ namespace Nuclex.Support.Collections {
}
/// Release all resources owned by the instance explicitely
- void IDisposable.Dispose() {
+ public void Dispose() {
Dispose(true); // Called by user
}
diff --git a/Source/Collections/PriorityQueue.cs b/Source/Collections/PriorityQueue.cs
index eba6207..f61d845 100644
--- a/Source/Collections/PriorityQueue.cs
+++ b/Source/Collections/PriorityQueue.cs
@@ -3,233 +3,391 @@ using System.Collections.Generic;
using System.Collections;
namespace Nuclex.Support.Collections {
-/*
- /// Queue that dequeues items in order of their priority
- public class PriorityQueue : ICollection, IEnumerable {
+ /*
+ public class PriorityQueue : ICollection {
+
+ private struct HeapEntry {
+
+ public HeapEntry(object item, int priority) {
+ this.item = item;
+ this.priority = priority;
+ }
+ public object Item {
+ get { return item; }
+ }
+ public int Priority {
+ get { return priority; }
+ }
+
+ private object item;
+ private int priority;
- public static PriorityQueue Syncronized(PriorityQueue P) {
- return new PriorityQueue(ArrayList.Synchronized(P.InnerList), P.Comparer, false);
- }
- public static PriorityQueue ReadOnly(PriorityQueue P) {
- return new PriorityQueue(ArrayList.ReadOnly(P.InnerList), P.Comparer, false);
}
- public PriorityQueue()
- : this(Comparer.Default) { }
+ private int count;
+ private int capacity;
+ private int version;
+ private HeapEntry[] heap;
- public PriorityQueue(int C)
- : this(Comparer.Default, C) { }
-
- public PriorityQueue(IComparer c) {
- Comparer = c;
+ public PriorityQueue() {
+ capacity = 15; // 15 is equal to 4 complete levels
+ heap = new HeapEntry[capacity];
}
- public PriorityQueue(IComparer c, int Capacity) {
- Comparer = c;
- InnerList.Capacity = Capacity;
- }
-
- protected PriorityQueue(ArrayList Core, IComparer Comp, bool Copy) {
- if(Copy)
- InnerList = Core.Clone() as ArrayList;
- else
- InnerList = Core;
- Comparer = Comp;
- }
-
- protected void SwitchElements(int i, int j) {
- object h = InnerList[i];
- InnerList[i] = InnerList[j];
- InnerList[j] = h;
- }
-
- protected virtual int OnCompare(int i, int j) {
- return Comparer.Compare(InnerList[i], InnerList[j]);
- }
-
- #region public methods
- ///
- /// Push an object onto the PQ
- ///
- /// The new object
- ///
- /// The index in the list where the object is _now_. This will change when
- /// objects are taken from or put onto the PQ.
- ///
- public int Queue(object O) {
- int p = InnerList.Count, p2;
- InnerList.Add(O); // E[p] = O
- do {
- if(p == 0)
- break;
- p2 = (p - 1) / 2;
- if(OnCompare(p, p2) < 0) {
- SwitchElements(p, p2);
- p = p2;
- } else
- break;
- } while(true);
- return p;
- }
-
- ///
- /// Get the smallest object and remove it.
- ///
- /// The smallest object
public object Dequeue() {
- object result = InnerList[0];
- int p = 0, p1, p2, pn;
- InnerList[0] = InnerList[InnerList.Count - 1];
- InnerList.RemoveAt(InnerList.Count - 1);
- do {
- pn = p;
- p1 = 2 * p + 1;
- p2 = 2 * p + 2;
- if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
- p = p1;
- if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
- p = p2;
+ if(count == 0)
+ throw new InvalidOperationException();
- if(p == pn)
- break;
- SwitchElements(p, pn);
- } while(true);
+ object result = heap[0].Item;
+ count--;
+ trickleDown(0, heap[count]);
+ version++;
return result;
}
- ///
- /// Notify the PQ that the object at position i has changed
- /// and the PQ needs to restore order.
- /// Since you dont have access to any indexes (except by using the
- /// explicit IList.this) you should not call this function without knowing exactly
- /// what you do.
- ///
- /// The index of the changed object.
- public void Update(int i) {
- int p = i, pn;
- int p1, p2;
- do // aufsteigen
- {
- if(p == 0)
- break;
- p2 = (p - 1) / 2;
- if(OnCompare(p, p2) < 0) {
- SwitchElements(p, p2);
- p = p2;
- } else
- break;
- } while(true);
- if(p < i)
- return;
- do // absteigen
- {
- pn = p;
- p1 = 2 * p + 1;
- p2 = 2 * p + 2;
- if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
- p = p1;
- if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
- p = p2;
-
- if(p == pn)
- break;
- SwitchElements(p, pn);
- } while(true);
+ public void Enqueue(object item, int priority) {
+ if(count == capacity)
+ growHeap();
+ count++;
+ bubbleUp(count - 1, new HeapEntry(item, priority));
+ version++;
}
- ///
- /// Get the smallest object without removing it.
- ///
- /// The smallest object
- public object Peek() {
- if(InnerList.Count > 0)
- return InnerList[0];
- return null;
- }
-
- public bool Contains(object value) {
- return InnerList.Contains(value);
- }
-
- public void Clear() {
- InnerList.Clear();
- }
-
- public int Count {
- get {
- return InnerList.Count;
+ private void bubbleUp(int index, HeapEntry he) {
+ int parent = getParent(index);
+ // note: (index > 0) means there is a parent
+ while((index > 0) && (heap[parent].Priority < he.Priority)) {
+ heap[index] = heap[parent];
+ index = parent;
+ parent = getParent(index);
}
+ heap[index] = he;
}
- IEnumerator IEnumerable.GetEnumerator() {
- return InnerList.GetEnumerator();
+
+ private int getLeftChild(int index) {
+ return (index * 2) + 1;
+ }
+
+ private int getParent(int index) {
+ return (index - 1) / 2;
+ }
+
+ private void growHeap() {
+ capacity = (capacity * 2) + 1;
+ HeapEntry[] newHeap = new HeapEntry[capacity];
+ System.Array.Copy(heap, 0, newHeap, 0, count);
+ heap = newHeap;
+ }
+
+ private void trickleDown(int index, HeapEntry he) {
+ int child = getLeftChild(index);
+ while(child < count) {
+ if(((child + 1) < count) &&
+ (heap[child].Priority < heap[child + 1].Priority)) {
+ child++;
+ }
+ heap[index] = heap[child];
+ index = child;
+ child = getLeftChild(index);
+ }
+ bubbleUp(index, he);
+ }
+
+ #region IEnumerable implementation
+ public IEnumerator GetEnumerator() {
+ return new PriorityQueueEnumerator(this);
+ }
+ #endregion
+
+ #region ICollection implementation
+ public int Count {
+ get { return count; }
}
public void CopyTo(Array array, int index) {
- InnerList.CopyTo(array, index);
- }
-
- public object Clone() {
- return new PriorityQueue(InnerList, Comparer, true);
- }
-
- public bool IsSynchronized {
- get {
- return InnerList.IsSynchronized;
- }
+ System.Array.Copy(heap, 0, array, index, count);
}
public object SyncRoot {
- get {
- return this;
- }
- }
- #endregion
- #region explicit implementation
- bool IList.IsReadOnly {
- get {
- return false;
- }
+ get { return this; }
}
- object IList.this[int index] {
- get {
- return InnerList[index];
- }
- set {
- InnerList[index] = value;
- Update(index);
- }
- }
-
- int IList.Add(object o) {
- return Queue(o);
- }
-
- void IList.RemoveAt(int index) {
- throw new NotSupportedException();
- }
-
- void IList.Insert(int index, object value) {
- throw new NotSupportedException();
- }
-
- void IList.Remove(object value) {
- throw new NotSupportedException();
- }
-
- int IList.IndexOf(object value) {
- throw new NotSupportedException();
- }
-
- bool IList.IsFixedSize {
- get {
- return false;
- }
+ public bool IsSynchronized {
+ get { return false; }
+ }
+ #endregion
+
+ #region Priority Queue enumerator
+ private class PriorityQueueEnumerator : IEnumerator {
+ private int index;
+ private PriorityQueue pq;
+ private int version;
+
+ public PriorityQueueEnumerator(PriorityQueue pq) {
+ this.pq = pq;
+ Reset();
+ }
+
+ private void checkVersion() {
+ if(version != pq.version)
+ throw new InvalidOperationException();
+ }
+
+ #region IEnumerator Members
+
+ public void Reset() {
+ index = -1;
+ version = pq.version;
+ }
+
+ public object Current {
+ get {
+ checkVersion();
+ return pq.heap[index].Item;
+ }
+ }
+
+ public bool MoveNext() {
+ checkVersion();
+ if(index + 1 == pq.count)
+ return false;
+ index++;
+ return true;
+ }
+
+ #endregion
}
#endregion
- protected ArrayList InnerList = new ArrayList();
- protected IComparer Comparer;
}
-*/
+ */
+ /*
+ /// Queue that dequeues items in order of their priority
+ public class PriorityQueue : ICollection, IEnumerable {
+
+ public static PriorityQueue Syncronized(PriorityQueue P) {
+ return new PriorityQueue(ArrayList.Synchronized(P.InnerList), P.Comparer, false);
+ }
+ public static PriorityQueue ReadOnly(PriorityQueue P) {
+ return new PriorityQueue(ArrayList.ReadOnly(P.InnerList), P.Comparer, false);
+ }
+
+ public PriorityQueue()
+ : this(Comparer.Default) { }
+
+ public PriorityQueue(int C)
+ : this(Comparer.Default, C) { }
+
+ public PriorityQueue(IComparer c) {
+ Comparer = c;
+ }
+
+ public PriorityQueue(IComparer c, int Capacity) {
+ Comparer = c;
+ InnerList.Capacity = Capacity;
+ }
+
+ protected PriorityQueue(ArrayList Core, IComparer Comp, bool Copy) {
+ if(Copy)
+ InnerList = Core.Clone() as ArrayList;
+ else
+ InnerList = Core;
+ Comparer = Comp;
+ }
+
+ protected void SwitchElements(int i, int j) {
+ object h = InnerList[i];
+ InnerList[i] = InnerList[j];
+ InnerList[j] = h;
+ }
+
+ protected virtual int OnCompare(int i, int j) {
+ return Comparer.Compare(InnerList[i], InnerList[j]);
+ }
+
+ #region public methods
+ ///
+ /// Push an object onto the PQ
+ ///
+ /// The new object
+ ///
+ /// The index in the list where the object is _now_. This will change when
+ /// objects are taken from or put onto the PQ.
+ ///
+ public int Queue(object O) {
+ int p = InnerList.Count, p2;
+ InnerList.Add(O); // E[p] = O
+ do {
+ if(p == 0)
+ break;
+ p2 = (p - 1) / 2;
+ if(OnCompare(p, p2) < 0) {
+ SwitchElements(p, p2);
+ p = p2;
+ } else
+ break;
+ } while(true);
+ return p;
+ }
+
+ ///
+ /// Get the smallest object and remove it.
+ ///
+ /// The smallest object
+ public object Dequeue() {
+ object result = InnerList[0];
+ int p = 0, p1, p2, pn;
+ InnerList[0] = InnerList[InnerList.Count - 1];
+ InnerList.RemoveAt(InnerList.Count - 1);
+ do {
+ pn = p;
+ p1 = 2 * p + 1;
+ p2 = 2 * p + 2;
+ if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
+ p = p1;
+ if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
+ p = p2;
+
+ if(p == pn)
+ break;
+ SwitchElements(p, pn);
+ } while(true);
+ return result;
+ }
+
+ ///
+ /// Notify the PQ that the object at position i has changed
+ /// and the PQ needs to restore order.
+ /// Since you dont have access to any indexes (except by using the
+ /// explicit IList.this) you should not call this function without knowing exactly
+ /// what you do.
+ ///
+ /// The index of the changed object.
+ public void Update(int i) {
+ int p = i, pn;
+ int p1, p2;
+ do // aufsteigen
+ {
+ if(p == 0)
+ break;
+ p2 = (p - 1) / 2;
+ if(OnCompare(p, p2) < 0) {
+ SwitchElements(p, p2);
+ p = p2;
+ } else
+ break;
+ } while(true);
+ if(p < i)
+ return;
+ do // absteigen
+ {
+ pn = p;
+ p1 = 2 * p + 1;
+ p2 = 2 * p + 2;
+ if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
+ p = p1;
+ if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
+ p = p2;
+
+ if(p == pn)
+ break;
+ SwitchElements(p, pn);
+ } while(true);
+ }
+
+ ///
+ /// Get the smallest object without removing it.
+ ///
+ /// The smallest object
+ public object Peek() {
+ if(InnerList.Count > 0)
+ return InnerList[0];
+ return null;
+ }
+
+ public bool Contains(object value) {
+ return InnerList.Contains(value);
+ }
+
+ public void Clear() {
+ InnerList.Clear();
+ }
+
+ public int Count {
+ get {
+ return InnerList.Count;
+ }
+ }
+ IEnumerator IEnumerable.GetEnumerator() {
+ return InnerList.GetEnumerator();
+ }
+
+ public void CopyTo(Array array, int index) {
+ InnerList.CopyTo(array, index);
+ }
+
+ public object Clone() {
+ return new PriorityQueue(InnerList, Comparer, true);
+ }
+
+ public bool IsSynchronized {
+ get {
+ return InnerList.IsSynchronized;
+ }
+ }
+
+ public object SyncRoot {
+ get {
+ return this;
+ }
+ }
+ #endregion
+ #region explicit implementation
+ bool IList.IsReadOnly {
+ get {
+ return false;
+ }
+ }
+
+ object IList.this[int index] {
+ get {
+ return InnerList[index];
+ }
+ set {
+ InnerList[index] = value;
+ Update(index);
+ }
+ }
+
+ int IList.Add(object o) {
+ return Queue(o);
+ }
+
+ void IList.RemoveAt(int index) {
+ throw new NotSupportedException();
+ }
+
+ void IList.Insert(int index, object value) {
+ throw new NotSupportedException();
+ }
+
+ void IList.Remove(object value) {
+ throw new NotSupportedException();
+ }
+
+ int IList.IndexOf(object value) {
+ throw new NotSupportedException();
+ }
+
+ bool IList.IsFixedSize {
+ get {
+ return false;
+ }
+ }
+ #endregion
+
+ protected ArrayList InnerList = new ArrayList();
+ protected IComparer Comparer;
+ }
+ */
} // namespace Nuclex.Support.Collections
diff --git a/Source/Serialization/BinarySerializer.cs b/Source/Serialization/BinarySerializer.cs
index 179db38..17e259b 100644
--- a/Source/Serialization/BinarySerializer.cs
+++ b/Source/Serialization/BinarySerializer.cs
@@ -59,7 +59,7 @@ namespace Nuclex.Support.Serialization {
);
// Let the blueprint load its own data and add it to the collection
- ((IBinarySerializable)item).Load(reader);
+ (item as IBinarySerializable).Load(reader);
collection.Add(item);
} // for