sharperang/libpaperang/Helpers/CRC.cs

60 lines
1.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace libpaperang.Helpers {
public class CRC {
private uint _iv;
public uint iv { get => ~_iv; private set => _iv=~value; }
public uint mv = 0x35769521;
private uint poly = 0xedb88320;
private uint[] crctable;
public bool IsInitialised=false;
public CRC(bool autoinit = true) {
iv = 0;
if(autoinit) Initialise();
}
public CRC(uint iv, bool autoinit = true) {
this.iv = iv;
if (autoinit) Initialise();
}
public void Initialise() {
crctable=Enumerable.Range(0, 256).Select(i => {
uint e=(uint)i;
for (ushort eb = 0; eb<8; eb++)
e=((e&1)!=0)
? (poly^(e>>1))
: (e>>1);
return e;
}).ToArray();
IsInitialised=true;
}
public uint Reflect(uint iv) {
uint ivr=0;
for (int i = 0; i<32; i++) {
uint b=(iv>>i)&1;
ivr|=(b<<(31-i));
}
return ~ivr;
}
public uint GetChecksumUint<T>(IEnumerable<T> data) {
if (!IsInitialised) throw new CrcNotAvailableException();
try {
return ~data.Aggregate(_iv,
(cti, cb) => crctable[(cti&0xFF)^Convert.ToByte(cb)]^(cti>>8));
} catch (FormatException e) {
throw new FormatException("Could not read input as a byte stream", e);
} catch (InvalidCastException e) {
throw new InvalidCastException("Could not read input as a byte stream", e);
} catch (OverflowException e) {
throw new OverflowException("Could not read input as a byte stream", e);
}
}
public byte[] GetChecksumBytes<T>(IEnumerable<T> data) => BitConverter.GetBytes(GetChecksumUint(data));
public uint GetCrcIv() => iv == mv
? iv
: iv ^ mv;
public byte[] GetCrcIvBytes() => BitConverter.GetBytes(GetCrcIv());
}
}