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(IEnumerable 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(IEnumerable data) => BitConverter.GetBytes(GetChecksumUint(data)); public uint GetCrcIv() => iv == mv ? iv : iv ^ mv; public byte[] GetCrcIvBytes() => BitConverter.GetBytes(GetCrcIv()); } }