using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BotSharp.Models.CRFLite.Utils
{
///
/// Represents a generic interface of an ordered collection.
///
/// The type of elements in the collection.
public interface ISortedCollection : ICollection
{
///
/// Gets the comparer used to order items in the collection.
///
IComparer Comparer
{
get;
}
///
/// Get all items equal to or greater than the specified value, starting with the lowest index and moving forwards.
///
IEnumerable WhereGreaterOrEqual(T value);
///
/// Get all items less than or equal to the specified value, starting with the highest index and moving backwards.
///
IEnumerable WhereLessOrEqualBackwards(T value);
///
/// Gets the index of the first item greater than the specified value.
/// ///
int FirstIndexWhereGreaterThan(T value);
///
/// Gets the index of the last item less than the specified key.
///
int LastIndexWhereLessThan(T value);
///
/// Gets the item at the specified index.
///
T At(int index);
///
/// Removes the item at the specified index.
///
void RemoveAt(int index);
///
/// Get all items starting at the index, and moving forward.
///
IEnumerable ForwardFromIndex(int index);
///
/// Get all items starting at the index, and moving backward.
///
IEnumerable BackwardFromIndex(int index);
}
///
/// Represents a generic interface of ordered key/value pairs.
///
/// The type of the key.
/// The type of the value.
public interface ISortedDictionary : IDictionary
{
///
/// Get all items having a key equal to or greater than the specified key, starting with the lowest index and moving forwards.
///
IEnumerable> WhereGreaterOrEqual(TKey key);
///
/// Get all items less than or equal to the specified value, starting with the highest index and moving backwards.
///
IEnumerable> WhereLessOrEqualBackwards(TKey keyUpperBound);
///
/// Gets the sorted collection of keys.
///
new ISortedCollection Keys
{
get;
}
///
/// Gets the item at the specified index.
///
KeyValuePair At(int index);
///
/// Removes the item at the specified index.
///
void RemoveAt(int index);
///
/// Sets the value at the specified index.
///
///
///
void SetValueAt(int index, TValue value);
///
/// Get all items starting at the index, and moving forward.
///
IEnumerable> ForwardFromIndex(int index);
///
/// Get all items starting at the index, and moving backward.
///
IEnumerable> BackwardFromIndex(int index);
}
///
/// An O(log N) implementation of the ISortedDictionary interface.
///
/// The type for the sorted keys.
/// The type for the associated values.
public class BTreeDictionary : ISortedDictionary
{
#region Fields
Node root;
readonly Node first;
readonly KeyCollection keys;
readonly ValueCollection values;
readonly IComparer keyComparer;
private void ObjectInvariant()
{
}
#endregion
#region Construction
///
/// Initializes a new BTreeDictionary instance optimized for the specified node capacity.
///
/// The capacity in keys for each node in the tree structure.
public BTreeDictionary(int nodeCapacity = 128)
: this(Comparer.Default, nodeCapacity)
{
}
///
/// Initializes a new BTreeDictionary instance.
///
/// The comparer for ordering keys in the structure.
/// The capacity in keys for each node in the tree structure.
public BTreeDictionary(IComparer keyComparer, int nodeCapacity)
{
this.keyComparer = keyComparer;
this.first = new Node(nodeCapacity);
this.root = this.first;
this.keys = new KeyCollection(this);
this.values = new ValueCollection(this);
}
#endregion
#region Properties
///
/// Gets the value associated with the specified key. An arbitrary value will be chosen if key is a duplicate.
///
/// The key for which to retrieve the associated value.
/// The value associated with the key.
public TValue this[TKey key]
{
get
{
TValue result;
if (this.TryGetValue(key, out result))
return result;
throw new InvalidOperationException("error");
}
set
{
Node leaf;
int pos;
if (Node.Find(root, key, KeyComparer, 0, out leaf, out pos))
leaf.SetValue(pos, value);
else
{
Node.Insert(key, ref leaf, ref pos, ref root);
leaf.SetValue(pos, value);
}
}
}
///
/// Gets the number of key value pairs in the dictionary.
///
public int Count
{
get
{
return this.root.TotalCount;
}
}
///
/// Gets the key comparer.
///
public IComparer KeyComparer
{
get
{
return this.keyComparer;
}
}
///
/// Gets the collection of keys in the dictionary.
///
public ISortedCollection Keys
{
get
{
return this.keys;
}
}
public IList KeyList
{
get
{
return this.keys;
}
}
///
/// Gets the collection of values in the dictionary.
///
public ICollection Values
{
get
{
return this.values;
}
}
public IList ValueList
{
get
{
return this.values;
}
}
///
/// Gets or sets indication whether this dictionary is readonly or mutable.
///
public bool IsReadOnly
{
get;
set;
}
#endregion
#region Methods
///
/// Gets indication of whether the dictionary contains an entry for the specified key.
///
/// The key.
/// True if the dictionary contains the key; otherwise, false.
public bool ContainsKey(TKey key)
{
Node leaf;
int pos;
var found = Node.Find(root, key, KeyComparer, 0, out leaf, out pos);
return found;
}
///
/// Tries to get the value for the specified key. An arbitrary value will be chosen if key is a duplicate.
///
/// The key for which to try to get the value.
/// The value found for the specified key, or a default value if not found.
/// True if the value was found; otherwise, false.
public bool TryGetValue(TKey key, out TValue value)
{
try
{
Node leaf;
int pos;
var found = Node.Find(root, key, KeyComparer, 0, out leaf, out pos);
value = found ? leaf.GetValue(pos) : default(TValue);
return found;
}
catch (System.Exception)
{
value = default(TValue);
return false;
}
}
///
/// Adds the specified key and value to the dictionary.
///
/// The key to add.
/// The value to associate with the key.
public void Add(TKey key, TValue value)
{
Node leaf;
int pos;
var found = Node.Find(root, key, KeyComparer, 0, out leaf, out pos);
if (found)
{
//The key is already in the dictionary, throw exception out
throw new InvalidOperationException("The key is already in the dictionary");
}
Node.Insert(key, ref leaf, ref pos, ref root);
leaf.SetValue(pos, value);
}
///
/// Gets the key value pair at the specified index.
///
/// The index at which to get the key value pair.
/// The key value pair at the specified index.
public KeyValuePair At(int index)
{
var leaf = Node.LeafAt(root, ref index);
return new KeyValuePair(leaf.GetKey(index), leaf.GetValue(index));
}
///
/// Clears the dictionary of all items.
///
public void Clear()
{
Node.Clear(first);
root = first;
}
///
/// Remove the key and associated value from the dictionary.
///
/// The key to remove.
/// True if the key was removed; otherwise, false if key was not found.
public bool Remove(TKey key)
{
Node leaf;
int pos;
if (!Node.Find(root, key, KeyComparer, 0, out leaf, out pos))
return false;
Node.Remove(leaf, pos, ref root);
return true;
}
///
/// Removes the key and associated value from the dictionary at the specified index.
///
/// The index at which to remove the key value pair.
public void RemoveAt(int index)
{
var leaf = Node.LeafAt(root, ref index);
Node.Remove(leaf, index, ref root);
}
///
/// Get all items starting at the index, and moving forward.
///
public IEnumerable> ForwardFromIndex(int index)
{
var node = Node.LeafAt(root, ref index);
return Node.ForwardFromIndex(node, index);
}
///
/// Get all items starting at the index, and moving backward.
///
public IEnumerable> BackwardFromIndex(int index)
{
var node = Node.LeafAt(root, ref index);
return Node.BackwardFromIndex(node, index);
}
///
/// Sets the value at the specified index, leaving the key unchanged.
///
/// The index at which to set the value.
/// The value to associate at the specified index.
public void SetValueAt(int index, TValue value)
{
var leaf = Node.LeafAt(root, ref index);
leaf.SetValue(index, value);
}
///
/// Gets an enumerator of key value pairs for the entire collection in sorted ascending order.
///
///
public IEnumerator> GetEnumerator()
{
return Node.ForwardFromIndex(first, 0).GetEnumerator();
}
///
/// Gets an enumerator of key value pairs in ascending order by key, for all items with a key
/// equal or greater than the specified key lower bound.
///
/// The value at which to start returning keys.
/// All key value pairs having a key equal or greater than the lower bound, in key ascending order.
public IEnumerable> WhereGreaterOrEqual(TKey keyLowerBound)
{
Node leaf;
int leafPos;
Node.Find(root, keyLowerBound, KeyComparer, 0, out leaf, out leafPos);
return Node.ForwardFromIndex(leaf, leafPos);
}
///
/// Gets an enumerator of key value pairs in descending order by key, for all items with a key
/// less than or equal than the specified key upper bound.
///
/// The value at which to start returning keys.
/// All key value pairs having a key equal or less than the upper bound, in key descending order.
public IEnumerable> WhereLessOrEqualBackwards(TKey keyUpperBound)
{
Node leaf;
int leafPos;
var found = Node.Find(root, keyUpperBound, KeyComparer, 0, out leaf, out leafPos);
if (!found)
--leafPos;
return Node.BackwardFromIndex(leaf, leafPos);
}
///
/// Copy the entire dictionary to the specified array, starting at the specified array index.
///
/// The array into which to copy.
/// The index at which to start copying.
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
#endregion
#region Implementation - Nested Types
sealed class Node
{
#region Fields
readonly TKey[] keys;
readonly TValue[] values;
readonly Node[] nodes;
int nodeCount;
int totalCount;
Node parent;
Node next;
Node prev;
private void ObjectInvariant()
{
}
#endregion
#region Construction
///
/// Initialize the first node in the BTree structure.
///
public Node(int nodeCapacity)
: this(nodeCapacity, true)
{
}
#endregion
#region Properties
public int TotalCount
{
get
{
return this.totalCount;
}
}
public bool IsRoot
{
get
{
return this.parent == null;
}
}
public bool IsLeaf
{
get
{
return nodes == null;
}
}
public int NodeCount
{
get
{
return this.nodeCount;
}
}
#endregion
#region Methods
///
/// Gets the key at the specified position.
///
public TKey GetKey(int pos)
{
return this.keys[pos];
}
///
/// Gets the value at the specified position.
///
public TValue GetValue(int pos)
{
return this.values[pos];
}
///
/// Sets the value at the specified position.
///
public void SetValue(int pos, TValue value)
{
this.values[pos] = value;
}
///
/// Get the leaf node at the specified index in the tree defined by the specified root.
///
public static Node LeafAt(Node root, ref int pos)
{
int nodeIndex = 0;
while (true)
{
if (root.nodes == null)
{
return root;
}
var node = root.nodes[nodeIndex];
if (pos < node.totalCount)
{
root = node;
nodeIndex = 0;
}
else
{
pos -= node.totalCount;
++nodeIndex;
}
}
}
///
/// Find the node and index in the tree defined by the specified root.
///
public static bool Find(Node root, TKey key, IComparer keyComparer, int duplicatesBias, out Node leaf, out int pos)
{
pos = Array.BinarySearch(root.keys, 0, root.nodeCount, key, keyComparer);
while (root.nodes != null)
{
if (pos >= 0)
{
if (duplicatesBias != 0)
MoveToDuplicatesBoundary(key, keyComparer, duplicatesBias, ref root, ref pos);
// Found an exact match. Move down one level.
root = root.nodes[pos];
}
else
{
// No exact match. Find greatest lower bound.
pos = ~pos;
if (pos > 0)
--pos;
root = root.nodes[pos];
}
pos = Array.BinarySearch(root.keys, 0, root.nodeCount, key, keyComparer);
}
leaf = root;
if (pos < 0)
{
pos = ~pos;
return false;
}
if (duplicatesBias != 0)
MoveToDuplicatesBoundary(key, keyComparer, duplicatesBias, ref leaf, ref pos);
return true;
}
///
/// Insert a new key into the leaf node at the specified position.
///
public static void Insert(TKey key, ref Node leaf, ref int pos, ref Node root)
{
// Make sure there is space for the new key.
if (EnsureSpace(leaf, ref root) && pos > leaf.nodeCount)
{
pos -= leaf.nodeCount;
leaf = leaf.next;
}
// Insert the key.
int moveCount = leaf.nodeCount - pos;
Array.Copy(leaf.keys, pos, leaf.keys, pos + 1, moveCount);
leaf.keys[pos] = key;
++leaf.nodeCount;
EnsureParentKey(leaf, pos);
// Insert space for the value. Caller is responsible for filling in value.
Array.Copy(leaf.values, pos, leaf.values, pos + 1, moveCount);
// Update total counts.
for (var node = leaf; node != null; node = node.parent)
++node.totalCount;
}
///
/// Remove the item from the node at the specified position.
///
public static bool Remove(Node leaf, int pos, ref Node root)
{
// Update total counts.
for (var node = leaf; node != null; node = node.parent)
--node.totalCount;
// Remove the key and value from the node.
--leaf.nodeCount;
Array.Copy(leaf.keys, pos + 1, leaf.keys, pos, leaf.nodeCount - pos);
Array.Copy(leaf.values, pos + 1, leaf.values, pos, leaf.nodeCount - pos);
leaf.keys[leaf.nodeCount] = default(TKey);
leaf.values[leaf.nodeCount] = default(TValue);
// Make sure parent keys index correctly into this node.
if (leaf.nodeCount > 0)
EnsureParentKey(leaf, pos);
// Merge this node with others if it is below the node capacity threshold.
Merge(leaf, ref root);
return true;
}
///
/// Get an ascending enumerable for the collection, starting an the index in the specified leaf node.
///
public static IEnumerable> ForwardFromIndex(Node leaf, int pos)
{
while (leaf != null)
{
while (pos < leaf.nodeCount)
{
yield return new KeyValuePair(leaf.GetKey(pos), leaf.GetValue(pos));
++pos;
}
pos -= leaf.nodeCount;
leaf = leaf.next;
}
}
///
/// Get a descending enumerable, starting at the index in the specified leaf node.
///
public static IEnumerable> BackwardFromIndex(Node leaf, int pos)
{
if (pos == -1)
{
// Handle special case to start moving in the previous node.
leaf = leaf.prev;
if (leaf != null)
pos = leaf.nodeCount - 1;
else
pos = 0;
}
else if (pos == leaf.NodeCount)
{
// Handle special case to start moving in the next node.
if (leaf.next == null)
--pos;
else
{
leaf = leaf.next;
pos = 0;
}
}
// Loop thru collection, yielding each value in sequence.
while (leaf != null)
{
while (pos >= 0)
{
yield return new KeyValuePair(leaf.GetKey(pos), leaf.GetValue(pos));
--pos;
}
leaf = leaf.prev;
if (leaf != null)
pos += leaf.nodeCount;
}
}
///
/// Clear all keys and values from the specified node.
///
public static void Clear(Node firstNode)
{
int clearCount = firstNode.nodeCount;
Array.Clear(firstNode.keys, 0, clearCount);
Array.Clear(firstNode.values, 0, clearCount);
firstNode.nodeCount = 0;
firstNode.totalCount = 0;
firstNode.parent = null;
firstNode.next = null;
}
///
/// Get the index relative to the root node, for the position in the specified leaf.
///
public static int GetRootIndex(Node leaf, int pos)
{
var node = leaf;
var rootIndex = pos;
while (node.parent != null)
{
int nodePos = Array.IndexOf(node.parent.nodes, node, 0, node.parent.nodeCount);
for (int i = 0; i < nodePos; ++i)
rootIndex += node.parent.nodes[i].totalCount;
node = node.parent;
}
return rootIndex;
}
#endregion
#region Implementation
Node(int nodeCapacity, bool leaf)
{
this.keys = new TKey[nodeCapacity];
if (leaf)
{
this.values = new TValue[nodeCapacity];
this.nodes = null;
}
else
{
this.values = null;
this.nodes = new Node[nodeCapacity];
}
this.nodeCount = 0;
this.totalCount = 0;
this.parent = null;
this.next = null;
this.prev = null;
}
///
/// (Assumes: key is a duplicate in node at pos) Move to the side on the range of duplicates,
/// as indicated by the sign of duplicatesBias.
///
///
///
///
///
///
static void MoveToDuplicatesBoundary(TKey key, IComparer keyComparer, int duplicatesBias, ref Node node, ref int pos)
{
// Technically, we could adjust the binary search to perform most of this step, but duplicates
// are usually unexpected.. algorithm is still O(log N), because scan include at most a scan thru two nodes
// worth of keys, for each level.
// Also, the binary search option would still need the ugliness of the special case for moving into the
// previous node; it would only be a little faster, on average, assuming large numbers of duplicates were common.
if (duplicatesBias < 0)
{
// Move backward over duplicates.
while (pos > 0 && 0 == keyComparer.Compare(node.keys[pos - 1], key))
--pos;
// Special case: duplicates can span backwards into the previous node because the parent
// key pivot might be in the center for the duplicates.
if (pos == 0 && node.prev != null)
{
var prev = node.prev;
var prevPos = prev.NodeCount;
while (prevPos > 0 && 0 == keyComparer.Compare(prev.keys[prevPos - 1], key))
{
--prevPos;
}
if (prevPos < prev.NodeCount)
{
node = prev;
pos = prevPos;
}
}
}
else
{
// Move forward over duplicates.
while (pos < node.NodeCount - 1 && 0 == keyComparer.Compare(node.keys[pos + 1], key))
++pos;
}
}
static bool EnsureSpace(Node node, ref Node root)
{
if (node.nodeCount < node.keys.Length)
return false;
EnsureParent(node, ref root);
EnsureSpace(node.parent, ref root);
var sibling = new Node(node.keys.Length, node.nodes == null);
sibling.next = node.next;
sibling.prev = node;
sibling.parent = node.parent;
if (node.next != null)
node.next.prev = sibling;
node.next = sibling;
int pos = Array.IndexOf(node.parent.nodes, node, 0, node.parent.nodeCount);
int siblingPos = pos + 1;
Array.Copy(node.parent.keys, siblingPos, node.parent.keys, siblingPos + 1, node.parent.nodeCount - siblingPos);
Array.Copy(node.parent.nodes, siblingPos, node.parent.nodes, siblingPos + 1, node.parent.nodeCount - siblingPos);
++node.parent.nodeCount;
node.parent.nodes[siblingPos] = sibling;
int half = node.nodeCount / 2;
int halfCount = node.nodeCount - half;
Move(node, half, sibling, 0, halfCount);
return true;
}
static void Move(Node source, int sourceIndex, Node target, int targetIndex, int moveCount)
{
Move(source.keys, sourceIndex, source.nodeCount, target.keys, targetIndex, target.nodeCount, moveCount);
if (source.values != null)
Move(source.values, sourceIndex, source.nodeCount, target.values, targetIndex, target.nodeCount, moveCount);
int totalMoveCount;
if (source.nodes == null)
{
totalMoveCount = moveCount;
}
else
{
Move(source.nodes, sourceIndex, source.nodeCount, target.nodes, targetIndex, target.nodeCount, moveCount);
totalMoveCount = 0;
for (int i = 0; i < moveCount; ++i)
{
var child = target.nodes[targetIndex + i];
child.parent = target;
totalMoveCount += child.totalCount;
}
}
source.nodeCount -= moveCount;
target.nodeCount += moveCount;
var sn = source;
var tn = target;
while (sn != null && sn != tn)
{
sn.totalCount -= totalMoveCount;
tn.totalCount += totalMoveCount;
sn = sn.parent;
tn = tn.parent;
}
EnsureParentKey(source, sourceIndex);
EnsureParentKey(target, targetIndex);
}
static void Move(TItem[] source, int sourceIndex, int sourceTotal, TItem[] target, int targetIndex, int targetTotal, int count)
{
Array.Copy(target, targetIndex, target, targetIndex + count, targetTotal - targetIndex);
Array.Copy(source, sourceIndex, target, targetIndex, count);
Array.Copy(source, sourceIndex + count, source, sourceIndex, sourceTotal - sourceIndex - count);
Array.Clear(source, sourceTotal - count, count);
}
static void EnsureParent(Node node, ref Node root)
{
if (node.parent != null)
return;
var parent = new Node(node.keys.Length, false);
parent.totalCount = node.totalCount;
parent.nodeCount = 1;
parent.keys[0] = node.keys[0];
parent.nodes[0] = node;
node.parent = parent;
root = parent;
}
static void EnsureParentKey(Node node, int pos)
{
while (pos == 0 && node.parent != null)
{
pos = Array.IndexOf(node.parent.nodes, node, 0, node.parent.nodeCount);
node.parent.keys[pos] = node.keys[0];
node = node.parent;
}
}
static void Merge(Node node, ref Node root)
{
if (node.nodeCount == 0)
{
// Handle special case: Empty node.
if (node.parent == null)
return;
// Remove the node from the parent nodes.
int pos = Array.IndexOf(node.parent.nodes, node, 0, node.parent.nodeCount);
--node.parent.nodeCount;
Array.Copy(node.parent.keys, pos + 1, node.parent.keys, pos, node.parent.nodeCount - pos);
Array.Copy(node.parent.nodes, pos + 1, node.parent.nodes, pos, node.parent.nodeCount - pos);
node.parent.keys[node.parent.nodeCount] = default(TKey);
node.parent.nodes[node.parent.nodeCount] = null;
// Make sure parent (of the parent) keys link down correctly.
if (node.parent.nodeCount > 0)
EnsureParentKey(node.parent, pos);
// Delete the node from the next/prev linked list.
node.prev.next = node.next;
if (node.next != null)
node.next.prev = node.prev;
// Merge the parent node.
Merge(node.parent, ref root);
return;
}
if (node.next == null)
{
if (node.parent == null && node.nodeCount == 1 && node.nodes != null)
{
root = node.nodes[0];
root.parent = null;
}
return;
}
if (node.nodeCount >= node.keys.Length / 2)
return;
int count = node.next.nodeCount;
if (node.nodeCount + count > node.keys.Length)
count -= (node.nodeCount + count) / 2;
Move(node.next, 0, node, node.nodeCount, count);
Merge(node.next, ref root);
}
#endregion
}
abstract class KeyValueCollectionBase : ICollection
{
#region Fields
protected readonly BTreeDictionary tree;
#endregion
#region Construction
public KeyValueCollectionBase(BTreeDictionary tree)
{
this.tree = tree;
}
#endregion
#region Properties
public int Count
{
get
{
return tree.Count;
}
}
#endregion
#region Methods
public abstract bool Contains(T item);
public void CopyTo(T[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
public abstract IEnumerator GetEnumerator();
#endregion
#region ICollection<> members
void ICollection.Add(T item)
{
throw new NotSupportedException();
}
void ICollection.Clear()
{
throw new NotSupportedException();
}
bool ICollection.IsReadOnly
{
get
{
return true;
}
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
sealed class ValueCollection : KeyValueCollectionBase, IList
{
#region Construction
public ValueCollection(BTreeDictionary tree)
: base(tree)
{
}
#endregion
#region Methods
public override bool Contains(TValue item)
{
return this.tree.Any(keyValue => object.Equals(item, keyValue.Value));
}
public override IEnumerator GetEnumerator()
{
return this.tree.Select(keyValue => keyValue.Value).GetEnumerator();
}
#endregion
int IList.IndexOf(TValue item)
{
throw new NotImplementedException();
}
void IList.Insert(int index, TValue item)
{
throw new NotImplementedException();
}
void IList.RemoveAt(int index)
{
throw new NotImplementedException();
}
public TValue this[int index]
{
get
{
return this.tree.At(index).Value;
}
set
{
throw new NotImplementedException();
}
}
}
sealed class KeyCollection : KeyValueCollectionBase, ISortedCollection, IList
{
#region Construction
public KeyCollection(BTreeDictionary tree)
: base(tree)
{
}
#endregion
#region Properties
public IComparer Comparer
{
get
{
return tree.KeyComparer;
}
}
#endregion
#region Methods
public int FirstIndexWhereGreaterThan(TKey value)
{
Node leaf;
int pos;
var found = Node.Find(tree.root, value, tree.KeyComparer, 0, out leaf, out pos);
int result = Node.GetRootIndex(leaf, pos);
if (found)
++result;
return result;
}
public int LastIndexWhereLessThan(TKey value)
{
Node leaf;
int pos;
var found = Node.Find(tree.root, value, tree.KeyComparer, 0, out leaf, out pos);
int result = Node.GetRootIndex(leaf, pos);
if (found)
--result;
return result;
}
public TKey At(int index)
{
return this.tree.At(index).Key;
}
public override bool Contains(TKey item)
{
return tree.ContainsKey(item);
}
public override IEnumerator GetEnumerator()
{
return tree.Select(keyValue => keyValue.Key).GetEnumerator();
}
public IEnumerable WhereGreaterOrEqual(TKey lowerBound)
{
return tree.WhereGreaterOrEqual(lowerBound).Select(keyValue => keyValue.Key);
}
public IEnumerable WhereLessOrEqualBackwards(TKey upperBound)
{
return tree.WhereLessOrEqualBackwards(upperBound).Select(keyValue => keyValue.Key);
}
public IEnumerable ForwardFromIndex(int index)
{
return this.tree.ForwardFromIndex(index).Select(item => item.Key);
}
public IEnumerable BackwardFromIndex(int index)
{
return this.tree.BackwardFromIndex(index).Select(item => item.Key);
}
#endregion
#region IEnumerable members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
#region ISortedCollection<> members
void ISortedCollection.RemoveAt(int index)
{
throw new NotSupportedException();
}
#endregion
int IList.IndexOf(TKey item)
{
throw new NotImplementedException();
}
void IList.Insert(int index, TKey item)
{
throw new NotImplementedException();
}
void IList.RemoveAt(int index)
{
throw new NotImplementedException();
}
public TKey this[int index]
{
get
{
return this.tree.At(index).Key;
}
set
{
throw new NotImplementedException();
}
}
}
#endregion
#region IDictionary<> members
ICollection IDictionary.Keys
{
get
{
return this.Keys;
}
}
#endregion
#region ICollection<> members
void ICollection>.Add(KeyValuePair item)
{
this.Add(item.Key, item.Value);
}
bool ICollection>.Contains(KeyValuePair item)
{
TValue value;
return this.TryGetValue(item.Key, out value) && object.Equals(item.Value, value);
}
bool ICollection>.IsReadOnly
{
get
{
return false;
}
}
bool ICollection>.Remove(KeyValuePair item)
{
TValue value;
if (this.TryGetValue(item.Key, out value) && object.Equals(item.Value, value))
{
this.Remove(item.Key);
return true;
}
return false;
}
#endregion
#region IEnumerable members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
}