Last active
September 20, 2018 22:08
-
-
Save mjs3339/5044f2dd8fbfc7108b54a179c9f02fc5 to your computer and use it in GitHub Desktop.
C# - Generic Fixed Size Buffer Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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