#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; } } }