Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active September 20, 2018 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/5044f2dd8fbfc7108b54a179c9f02fc5 to your computer and use it in GitHub Desktop.
Save mjs3339/5044f2dd8fbfc7108b54a179c9f02fc5 to your computer and use it in GitHub Desktop.
C# - Generic Fixed Size Buffer Class
[DebuggerTypeProxy(typeof(HashSetDebugViewInt<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public struct TBuffer<T>
{
private int _size;
private Murmur3.Result[] _hashes;
private bool _hashesUpToDate;
public T[] Things;
private static readonly TypeCode _typeCode;
static TBuffer()
{
_typeCode = Type.GetTypeCode(typeof(T));
}
public void SetSize(int size)
{
_size = size;
Things = new T[size];
_hashes = new Murmur3.Result[size];
}
public void Resize(int size)
{
if(size == Things.Length)
return;
ResizeEx.Resize(ref Things, size);
ResizeEx.Resize(ref _hashes, size);
if(!_hashesUpToDate && CalculateHashesAsYouGo)
CalculateHashes();
}
public bool CalculateHashesAsYouGo{get; set;}
public T this[int index]
{
get
{
if(index > Things.Length)
throw new IndexOutOfRangeException("Error: Index out of range.");
return Things[index];
}
set
{
if(index + 1 > Things.Length)
throw new IndexOutOfRangeException("Error: Index out of range.");
Things[index] = value;
if(CalculateHashesAsYouGo)
{
_hashes[index] = GetHashCode(value);
_hashesUpToDate = true;
}
else
{
//_hashes[index] = new Murmur3.Result();
_hashesUpToDate = false;
}
}
}
private Murmur3.Result GetHashCode(T item)
{
switch(_typeCode)
{
case TypeCode.Boolean:
var t = (bool) (object) item;
return t.GetBytes().Hash128mm3r();
case TypeCode.Char:
var t1 = (char) (object) item;
return t1.GetBytes().Hash128mm3r();
case TypeCode.SByte:
var t2 = (sbyte) (object) item;
return t2.GetBytes().Hash128mm3r();
case TypeCode.Byte:
var t3 = (byte) (object) item;
return t3.GetBytes().Hash128mm3r();
case TypeCode.Int16:
var t4 = (short) (object) item;
return t4.GetBytes().Hash128mm3r();
case TypeCode.UInt16:
var t5 = (ushort) (object) item;
return t5.GetBytes().Hash128mm3r();
case TypeCode.Int32:
var t6 = (int) (object) item;
return t6.GetBytes().Hash128mm3r();
case TypeCode.UInt32:
var t7 = (uint) (object) item;
return t7.GetBytes().Hash128mm3r();
case TypeCode.Single:
var t8 = (float) (object) item;
return t8.GetBytes().Hash128mm3r();
case TypeCode.DateTime:
var t9 = (DateTime) (object) item;
return t9.GetBytes().Hash128mm3r();
case TypeCode.String:
var t10 = (string) (object) item;
return t10.GetBytes().Hash128mm3r();
case TypeCode.Int64:
var t11 = (long) (object) item;
return t11.GetBytes().Hash128mm3r();
case TypeCode.UInt64:
var t12 = (ulong) (object) item;
return t12.GetBytes().Hash128mm3r();
case TypeCode.Double:
var t13 = (double) (object) item;
return t13.GetBytes().Hash128mm3r();
case TypeCode.Decimal:
var t14 = (decimal) (object) item;
return t14.GetBytes().Hash128mm3r();
default:
return item.GetObjBytes().Hash128mm3r();
}
}
public void Clear()
{
Things = new T[_size];
_hashes = new Murmur3.Result[_size];
_hashesUpToDate = false;
}
public void CalculateHashes()
{
var hl = _hashes.Length;
if(Things.Length > hl)
_hashes = new Murmur3.Result[Things.Length];
for(var i = 0; i < Things.Length; ++i)
_hashes[i] = GetHashCode(Things[i]);
_hashesUpToDate = true;
}
public bool Contains(T item)
{
return FindItem(item) != -1;
}
public int FindItem(T item)
{
if(!_hashesUpToDate)
CalculateHashes();
var h = GetHashCode(item);
for(var i = 0; i < Things.Length; ++i)
if(h.H1 == _hashes[i].H1 && h.H2 == _hashes[i].H2)
return i;
return-1;
}
public void Insert(IEnumerable<T> source, int offset = 0)
{
if(!(source is ICollection<T> coll))
return;
if(coll.Count + 1 + offset > Things.Length)
throw new IndexOutOfRangeException("Error: Index out of range.");
var ptr = offset;
foreach(var e in coll)
this[ptr++] = e;
}
public List<Murmur3.Result> FindDuplicateHashes()
{
if(!_hashesUpToDate)
CalculateHashes();
var tmpThis = this;
var dup = tmpThis._hashes
.Where((t, i1) => i1 < tmpThis._hashes.Length)
.GroupBy(i => i)
.Where(g => g.Count() > 1)
.Select(g => g.Key).ToList();
return dup;
}
public T FindItemFromHash(Murmur3.Result h)
{
var tmpThis = this;
return tmpThis.Things.Where((t, i) => h.H1 == tmpThis._hashes[i].H1 && h.H2 == tmpThis._hashes[i].H2).First();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment