#region Copyright 2011-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
namespace CSharpTest.Net.IO
{
/// Provides a simple CRC32 checksum for a set of bytes
[System.Diagnostics.DebuggerDisplay("{Value:X8}")]
public struct Crc32 : IEquatable, IEquatable
{
static readonly int[] Table;
static Crc32()
{
Table = new int[256];
for (uint i = 0; i < 256; i++)
{
uint crc = i;
for (uint j = 0; j < 8; j++)
crc = (crc >> 1) ^ (((crc & 1) == 1) ? 0xEDB88320u : 0);
//Note: table ordinal and value inverted to omit -1 start and end operation
Table[~i & 0x0ff] = ~unchecked((int)crc);
}
}
int _crc32;
/// Resumes the computation of a CRC32 value
public Crc32(int crc)
{ _crc32 = crc; }
/// Initailizes the Crc32 value to the checksum of the string as a series of 16-bit values
public Crc32(string text)
{ _crc32 = 0; Add(text); }
/// Initailizes the Crc32 value to the checksum of the bytes provided
public Crc32(byte[] bytes)
{ _crc32 = 0; Add(bytes, 0, bytes.Length); }
/// Returns the computed CRC32 value as a Hex string
public override string ToString() { return String.Format("{0:X8}", Value); }
/// Returns the computed CRC32 value
public int Value { get { return _crc32; } }
/// Adds a byte to the checksum
public void Add(byte b)
{
_crc32 = (((~_crc32 >> 8) & 0x00FFFFFF) ^ Table[(_crc32 ^ b) & 0x0ff]);
}
/// Adds a byte to the checksum
public static Crc32 operator +(Crc32 chksum, byte b)
{
chksum.Add(b);
return chksum;
}
/// Adds an entire array of bytes to the checksum
public void Add(byte[] bytes)
{ Add(bytes, 0, Check.NotNull(bytes).Length); }
/// Adds a range from an array of bytes to the checksum
public void Add(byte[] bytes, int start, int length)
{
Check.NotNull(bytes);
int end = start + length;
for (int i = start; i < end; i++)
_crc32 = (((~_crc32 >> 8) & 0x00FFFFFF) ^ Table[(_crc32 ^ bytes[i]) & 0x0ff]);
}
/// Adds an entire array of bytes to the checksum
public static Crc32 operator +(Crc32 chksum, byte[] bytes)
{
chksum.Add(bytes, 0, bytes.Length);
return chksum;
}
/// Adds a string to the checksum as a series of 16-bit values (big endian)
public void Add(string text)
{
foreach (char ch in Check.NotNull(text))
{
_crc32 = (((~_crc32 >> 8) & 0x00FFFFFF) ^ Table[(_crc32 ^ ((byte)ch >> 8)) & 0x0ff]);
_crc32 = (((~_crc32 >> 8) & 0x00FFFFFF) ^ Table[(_crc32 ^ ((byte)ch)) & 0x0ff]);
}
}
/// Adds a string to the checksum as a series of 16-bit values
public static Crc32 operator +(Crc32 chksum, string text)
{
chksum.Add(text);
return chksum;
}
/// Extracts the correct hash code
public override int GetHashCode() { return Value; }
/// Returns true if the other object is equal to this one
public override bool Equals(object obj)
{
return
(obj is Crc32 && _crc32 == ((Crc32)obj)._crc32) ||
(obj is int && Value == ((int)obj));
}
/// Returns true if the other object is equal to this one
public bool Equals(Crc32 other) { return _crc32 == other._crc32; }
/// Returns true if the CRC32 provided is equal to this one
public bool Equals(int crc32) { return Value == crc32; }
/// Compares the two objects for equality
public static bool operator ==(Crc32 x, Crc32 y) { return x._crc32 == y._crc32; }
/// Compares the two objects for equality
public static bool operator !=(Crc32 x, Crc32 y) { return x._crc32 != y._crc32; }
/// Compares the two objects for equality
public static bool operator ==(Crc32 x, int y) { return x.Value == y; }
/// Compares the two objects for equality
public static bool operator !=(Crc32 x, int y) { return x.Value != y; }
}
}