Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created December 17, 2018 07:53
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/d2ced08824903b827d7cdbe91cfe98b4 to your computer and use it in GitHub Desktop.
Save mjs3339/d2ced08824903b827d7cdbe91cfe98b4 to your computer and use it in GitHub Desktop.
C# ByteArray Class Manages an Array of Bytes
public class ByteArray : IFormattable, IComparable, IComparable<ByteArray>, IEquatable<ByteArray>
{
public byte[] bytes;
public ByteArray() : this(0)
{
}
public ByteArray(int size)
{
bytes = new byte[size];
Active = true;
}
public ByteArray(byte[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(string str)
{
var ba = str.GetBytes();
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(string str, int size = 0)
{
var ba = str.GetBytes();
if(size > ba.Length)
throw new Exception("Size exceeds buffer length.");
if(size == 0)
size = ba.Length;
bytes = new byte[size];
Buffer.BlockCopy(ba, 0, bytes, 0, size);
Active = true;
}
public ByteArray(sbyte[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(short[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(ushort[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(int[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(uint[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(long[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(ulong[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(decimal[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(float[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public ByteArray(double[] ba)
{
bytes = new byte[ba.Length];
Buffer.BlockCopy(ba, 0, bytes, 0, ba.Length);
Active = true;
}
public int Length => bytes.Length;
public bool Active {get; set;}
public byte this[int index]
{
get
{
if(index > bytes.Length)
throw new Exception("Error: Index out of range.");
return bytes[index];
}
set
{
if(index > bytes.Length)
throw new Exception("Error: Index out of range.");
bytes[index] = value;
}
}
public int CompareTo(object obj)
{
throw new NotImplementedException();
}
public int CompareTo(ByteArray other)
{
throw new NotImplementedException();
}
public bool Equals(ByteArray other)
{
if(bytes == null && other.bytes == null)
return true;
if(bytes != null && other.bytes == null)
return false;
if(bytes == null && other.bytes != null)
return false;
if(bytes == null)
return false;
if(other.bytes == null)
return false;
return Compare(bytes, other.bytes);
}
public string ToString(string format, IFormatProvider formatProvider)
{
throw new NotImplementedException();
}
public static explicit operator byte(ByteArray value)
{
return checked((byte) (long) value);
}
public static explicit operator sbyte(ByteArray value)
{
return checked((sbyte) (long) value);
}
public static explicit operator short(ByteArray value)
{
return checked((short) (long) value);
}
public static explicit operator ushort(ByteArray value)
{
return checked((ushort) (long) value);
}
public static explicit operator int(ByteArray value)
{
return checked((int) (long) value);
}
public static explicit operator uint(ByteArray value)
{
return checked((uint) (long) value);
}
public static explicit operator long(ByteArray value)
{
return ToIntAny(value.bytes, 0);
}
public static explicit operator ulong(ByteArray value)
{
return checked((ulong) (long) value);
}
public static explicit operator decimal(ByteArray value)
{
return(long) value;
}
public static explicit operator float(ByteArray value)
{
return(long) value;
}
public static explicit operator double(ByteArray value)
{
return(ulong) value;
}
[SecuritySafeCritical]
private static unsafe long ToIntAny(byte[] value, int startIndex)
{
if(value == null)
throw new Exception("Error: Value cannot be null.");
if((uint) startIndex >= value.Length)
throw new Exception("Error: StartIndex cannot be greater than or equal to the length of value.");
fixed(byte* pbyte = &value[startIndex])
{
if(value.Length == 8)
{
if(startIndex % 8 == 0)
return*(long*) pbyte;
var i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | *(pbyte + 3);
var i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | *(pbyte + 7);
return(uint) i2 | ((long) i1 << 32);
}
if(value.Length == 4)
{
if(startIndex % 4 == 0)
return*(int*) pbyte;
return(*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | *(pbyte + 3);
}
if(value.Length == 2)
{
if(startIndex % 2 == 0)
return*(short*) pbyte;
return(short) ((*pbyte << 8) | *(pbyte + 1));
}
if(value.Length == 1)
return*(char*) pbyte;
}
return-1;
}
public static ByteArray operator +(ByteArray a, ByteArray b)
{
return Add(a.bytes, b.bytes);
}
public static ByteArray operator +(ByteArray a, byte[] b)
{
return Add(a.bytes, b);
}
public static ByteArray operator +(ByteArray a, byte b)
{
return Add(a.bytes, new[] {b});
}
public static ByteArray operator +(ByteArray a)
{
return a;
}
public static bool operator ==(ByteArray a, ByteArray b)
{
return a.Equals(b);
}
public static bool operator !=(ByteArray a, ByteArray b)
{
return!a.Equals(b);
}
public static ByteArray operator &(ByteArray a, ByteArray b)
{
return And(a.bytes, b.bytes);
}
public static ByteArray operator |(ByteArray a, ByteArray b)
{
return Or(a.bytes, b.bytes);
}
public static ByteArray operator ^(ByteArray a, ByteArray b)
{
return Xor(a.bytes, b.bytes);
}
public static ByteArray operator ~(ByteArray a)
{
return Not(a.bytes);
}
public static ByteArray operator -(ByteArray a)
{
return Neg(a.bytes);
}
public static ByteArray operator %(ByteArray a, ByteArray b)
{
return Mod(a.bytes, b.bytes);
}
public static ByteArray operator *(ByteArray a, ByteArray b)
{
return Mul(a.bytes, b.bytes);
}
public static ByteArray operator /(ByteArray a, ByteArray b)
{
return Div(a.bytes, b.bytes);
}
public static ByteArray operator <<(ByteArray a, int shift)
{
if(shift > a.Length)
return new ByteArray(a.Length);
var t = new byte[a.Length];
for(var i = 0; i < a.Length - shift; ++i)
t[i] = a[i + shift];
return new ByteArray(t);
}
public static ByteArray operator >>(ByteArray a, int shift)
{
if(shift > a.Length)
return new ByteArray(a.Length);
var t = new byte[a.Length];
for(int i = shift, ptr = 0; i < a.Length; ++i, ptr++)
t[ptr] = a[i];
return new ByteArray(t);
}
private static ByteArray Div(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((left[i] / right[i]) & 0xff);
return new ByteArray(ret);
}
private static ByteArray Mul(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((left[i] * right[i]) & 0xff);
return new ByteArray(ret);
}
private static ByteArray Mod(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((left[i] % right[i]) & 0xff);
return new ByteArray(ret);
}
private static ByteArray Neg(byte[] left)
{
var l1 = left.Length;
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((short) -left[i] & 0xff);
return new ByteArray(ret);
}
private static ByteArray Not(byte[] left)
{
var l1 = left.Length;
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((ushort) ~left[i] & 0xff);
return new ByteArray(ret);
}
private static ByteArray Xor(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((left[i] ^ right[i]) & 0xff);
return new ByteArray(ret);
}
private static ByteArray Or(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) ((left[i] | right[i]) & 0xff);
return new ByteArray(ret);
}
private static ByteArray And(byte[] left, byte[] right)
{
var l1 = left.Length;
var l2 = right.Length;
if(l1 != l2)
throw new Exception("Error: left and right arrays lengths must be equal.");
var ret = new byte[l1];
for(var i = 0; i < l1; ++i)
ret[i] = (byte) (left[i] & right[i] & 0xff);
return new ByteArray(ret);
}
private static ByteArray Add(byte[] left, byte[] right)
{
var ab = left.ConcatEx(right);
if(right == null)
throw new Exception("Right side must not be null.");
if(left == null)
{
left = new byte[right.Length];
Buffer.BlockCopy(right, 0, left, 0, right.Length);
return new ByteArray(left);
;
}
var l1 = left.Length;
var l2 = right.Length;
var ret = new byte[l1 + l2];
Buffer.BlockCopy(left, 0, ret, 0, l1);
Buffer.BlockCopy(right, 0, ret, l1, l2);
return new ByteArray(ret);
}
public override string ToString()
{
var sb = new StringBuilder();
foreach(var b in bytes)
{
var hex = b.ToString("X2");
sb.Append(hex);
}
return sb.ToString();
}
public override bool Equals(object obj)
{
if(ReferenceEquals(null, obj)) return false;
return obj is ByteArray && Equals((ByteArray) obj);
}
public override int GetHashCode()
{
var h = new UniHash(UniHash.Alg.Hash32);
return bytes != null ? h.ComputeHash(bytes).ToInt() : 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[SecuritySafeCritical]
public static unsafe bool Compare(byte[] a1, byte[] a2)
{
if(a1 == null && a2 == null)
return true;
if(a1 == null || a2 == null || a1.Length != a2.Length)
return false;
fixed(byte* p1 = a1, p2 = a2)
{
var Len = a1.Length;
byte* x1 = p1, x2 = p2;
while(Len > 7)
{
if(*(long*) x2 != *(long*) x1)
return false;
x1 += 8;
x2 += 8;
Len -= 8;
}
switch(Len % 8)
{
case 0:
break;
case 7:
if(*(int*) x2 != *(int*) x1)
return false;
x1 += 4;
x2 += 4;
if(*(short*) x2 != *(short*) x1)
return false;
x1 += 2;
x2 += 2;
if(*x2 != *x1)
return false;
break;
case 6:
if(*(int*) x2 != *(int*) x1)
return false;
x1 += 4;
x2 += 4;
if(*(short*) x2 != *(short*) x1)
return false;
break;
case 5:
if(*(int*) x2 != *(int*) x1)
return false;
x1 += 4;
x2 += 4;
if(*x2 != *x1)
return false;
break;
case 4:
if(*(int*) x2 != *(int*) x1)
return false;
break;
case 3:
if(*(short*) x2 != *(short*) x1)
return false;
x1 += 2;
x2 += 2;
if(*x2 != *x1)
return false;
break;
case 2:
if(*(short*) x2 != *(short*) x1)
return false;
break;
case 1:
if(*x2 != *x1)
return false;
break;
}
return true;
}
}
public byte[] ToByteArray()
{
return bytes;
}
public BigInteger ToBigInteger()
{
return bytes.ToBigInteger();
}
public string ToBinaryString()
{
var idx = bytes.Length - 1;
var base2 = new StringBuilder(bytes.Length * 8);
var binary = Convert.ToString(bytes[idx], 2);
base2.Append(binary);
for(idx--; idx >= 0; idx--)
base2.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
return base2.ToString();
}
public int GreatestCommonDivisor()
{
var b = new List<byte>(bytes);
var g = new int[256];
for(var i = 0; i < b.Count; ++i)
for(var j = i + 1; j < b.Count; ++j)
g[Gcd(b[i], b[j])]++;
var mv = 0;
var index = -1;
for(var i = 2; i < 256; ++i)
if(g[i] > mv)
{
mv = g[i];
index = i;
}
return index;
}
private static byte Gcd(byte a, byte b)
{
while(b > 0)
{
var r = (byte) (a % b);
a = b;
b = r;
}
return a;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment