Cosmos/source2/IL2CPU/Cosmos.IL2CPU/SkipList.cs
blah38621_cp 92dcac4a51 Made a few improvements to the speed of the ILScanner, including caching the resolved plugs.
Added the possibility for an optimization step in the IL2CPU MSBuild task. Currently commented out, but should work fine with a few modifications to the optimizer.
Moved classes that are dependent on Cosmos from the Orvid.Graphics, into the Orvid.Graphics.Cosmos assembly. 
Re-factored the font mechanism, added partially working .fnt Font support. 
Added a Rectangle class, and a Vec2d class, which is the same as Vec2, except with doubles for the X and Y values.
Made a small aesthetic improvement to the output of the File2ByteArray Converter.
2011-09-03 21:05:46 +00:00

267 lines
No EOL
7.5 KiB
C#

// The original code came from http://igoro.com/archive/skip-lists-are-fascinating/,
// However, it barely resembles it anymore.
// I retrieved and made the initial version of this March 17, 2011.
// Last modified: March 18, 2011.
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace Orvid.Collections
{
public class SkipList
{
protected Node _head = new Node(new byte[] { }, null, 33);
/// <summary>
/// The main node that the rest of the list is based on.
/// </summary>
public Node Head
{
get
{
return _head;
}
}
protected Random _rand = new Random();
public Random Random
{
get
{
return _rand;
}
}
protected int _levels = 1;
/// <summary>
/// An Int32 representing how deep the list is.
/// </summary>
public int Levels
{
get
{
return _levels;
}
}
public SkipList()
{
_head = new Node(new byte[] { }, null, 33);
_rand = new Random();
_levels = 1;
}
/// <summary>
/// Adds an item to the skip list.
/// </summary>
public void Add(string key, System.Reflection.MethodBase value)
{
this.Insert(key, value);
}
/// <summary>
/// Inserts an item into the skip list.
/// </summary>
public void Insert(string key, System.Reflection.MethodBase value)
{
byte[] key2 = ASCIIEncoding.ASCII.GetBytes(key);
int level = 0;
for (int R = _rand.Next(); (R & 1) == 1; R >>= 1)
{
level++;
if (level == _levels)
{
_levels++;
break;
}
}
Node newNode = new Node(key2, value, level + 1);
Node cur = _head;
for (int i = _levels - 1; i >= 0; i--)
{
for (; cur.Next[i] != null; cur = cur.Next[i])
{
if (ArrayGreaterThan(cur.Next[i].Key, key2))
{
break;
}
}
if (i <= level)
{
newNode.Next[i] = cur.Next[i];
cur.Next[i] = newNode;
}
}
}
public void Clear()
{
_head = new Node(new byte[] { }, null, 33);
_rand = new Random();
_levels = 1;
System.GC.Collect();
}
/// <summary>
/// Returns whether a particular key already exists in the skip list
/// </summary>
public bool Contains(string key, out System.Reflection.MethodBase value)
{
byte[] value2 = ASCIIEncoding.ASCII.GetBytes(key);
for (int i = _levels - 1; i >= 0; i--)
{
for (Node cur = _head; cur.Next[i] != null; cur = cur.Next[i])
{
if (ArrayGreaterThan(cur.Next[i].Key, value2))
{
break;
}
else if (ArraysEqual(cur.Next[i].Key, value2))
{
value = cur.Next[i].Value;
return true;
}
}
}
value = null;
return false;
}
/// <summary>
/// Attempts to remove one occurrence of a particular key from the skip list. Returns
/// whether the key was found in the skip list.
/// </summary>
public bool Remove(string key)
{
byte[] value2 = ASCIIEncoding.ASCII.GetBytes(key);
bool found = false;
for (int i = _levels - 1; i >= 0; i--)
{
for (Node cur = _head; cur.Next[i] != null; cur = cur.Next[i])
{
if (ArraysEqual(cur.Next[i].Key, value2))
{
found = true;
cur.Next[i] = cur.Next[i].Next[i];
break;
}
if (ArrayGreaterThan(cur.Next[i].Key, value2))
{
break;
}
}
}
return found;
}
public IEnumerator<System.Reflection.MethodBase> GetEnumerator()
{
Node cur = _head.Next[0];
while (cur != null)
{
yield return cur.Value;
cur = cur.Next[0];
}
}
protected bool ArraysEqual(byte[] firstArray, byte[] secondArray)
{
if (firstArray.Length != secondArray.Length)
{
return false;
}
Int32 curlen = 0;
foreach (byte b in firstArray)
{
if (b != secondArray[curlen])
{
return false;
}
curlen++;
}
return true;
}
protected bool ArrayGreaterThan(byte[] firstArray, byte[] secondArray)
{
if (firstArray.Length != secondArray.Length)
{
return (firstArray.Length > secondArray.Length);
}
else
{
Int32 n1 = 0;
foreach (byte b in firstArray)
{
if (b != secondArray[n1])
{
if (b > secondArray[n1])
{
return true;
}
else if (b < secondArray[n1])
{
return false;
}
}
else
{
n1++;
}
}
return true;
}
}
public class Node
{
private Node[] next;
public Node[] Next
{
get
{
return this.next;
}
private set
{
this.next = value;
}
}
private byte[] key;
public byte[] Key
{
get
{
return key;
}
set
{
this.key = value;
}
}
private System.Reflection.MethodBase value;
public System.Reflection.MethodBase Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
public Node(byte[] key, System.Reflection.MethodBase value, int level)
{
this.key = key;
this.value = value;
this.next = new Node[level];
}
}
}
}