99 lines
2.7 KiB
C#
99 lines
2.7 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace Essgee.Utilities
|
|
{
|
|
public static class Crc32
|
|
{
|
|
static readonly uint[] crcTable;
|
|
static readonly uint crcPolynomial = 0xEDB88320;
|
|
static readonly uint crcSeed = 0xFFFFFFFF;
|
|
|
|
static Crc32()
|
|
{
|
|
crcTable = new uint[256];
|
|
|
|
for (int i = 0; i < 256; i++)
|
|
{
|
|
uint entry = (uint)i;
|
|
for (int j = 0; j < 8; j++)
|
|
{
|
|
if ((entry & 0x00000001) == 0x00000001)
|
|
entry = (entry >> 1) ^ crcPolynomial;
|
|
else
|
|
entry = (entry >> 1);
|
|
}
|
|
crcTable[i] = entry;
|
|
}
|
|
}
|
|
|
|
private static void VerifyStartAndLength(int dataLength, int segmentStart, int segmentLength)
|
|
{
|
|
if (segmentStart >= dataLength) throw new Crc32Exception("Segment start offset is greater than total length");
|
|
if (segmentLength > dataLength) throw new Crc32Exception("Segment length is greater than total length");
|
|
if ((segmentStart + segmentLength) > dataLength) throw new Crc32Exception("Segment end offset is greater than total length");
|
|
}
|
|
|
|
public static uint Calculate(FileInfo fileInfo)
|
|
{
|
|
return Calculate(fileInfo, 0, (int)fileInfo.Length);
|
|
}
|
|
|
|
public static uint Calculate(FileInfo fileInfo, int start, int length)
|
|
{
|
|
VerifyStartAndLength((int)fileInfo.Length, start, length);
|
|
|
|
using (FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
return Calculate(file, start, length);
|
|
}
|
|
}
|
|
|
|
public static uint Calculate(Stream stream)
|
|
{
|
|
return Calculate(stream, 0, (int)stream.Length);
|
|
}
|
|
|
|
public static uint Calculate(Stream stream, int start, int length)
|
|
{
|
|
VerifyStartAndLength((int)stream.Length, start, length);
|
|
|
|
uint crc = 0;
|
|
|
|
var lastStreamPosition = stream.Position;
|
|
|
|
byte[] data = new byte[length];
|
|
stream.Position = start;
|
|
stream.Read(data, 0, length);
|
|
crc = Calculate(data, 0, data.Length);
|
|
stream.Position = lastStreamPosition;
|
|
|
|
return crc;
|
|
}
|
|
|
|
public static uint Calculate(byte[] data)
|
|
{
|
|
return Calculate(data, 0, data.Length);
|
|
}
|
|
|
|
public static uint Calculate(byte[] data, int start, int length)
|
|
{
|
|
VerifyStartAndLength(data.Length, start, length);
|
|
|
|
uint crc = crcSeed;
|
|
for (int i = start; i < (start + length); i++)
|
|
crc = ((crc >> 8) ^ crcTable[data[i] ^ (crc & 0x000000FF)]);
|
|
return ~crc;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class Crc32Exception : Exception
|
|
{
|
|
public Crc32Exception() : base() { }
|
|
public Crc32Exception(string message) : base(message) { }
|
|
public Crc32Exception(string message, Exception innerException) : base(message, innerException) { }
|
|
public Crc32Exception(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
|
}
|
|
}
|