File: System\IO\Hashing\Crc32ParameterSet.Table.cs
Web Access
Project: src\src\libraries\System.IO.Hashing\src\System.IO.Hashing.csproj (System.IO.Hashing)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
 
namespace System.IO.Hashing
{
    public partial class Crc32ParameterSet
    {
        private static uint[] GenerateLookupTable(uint polynomial, bool reflectInput)
        {
            uint[] table = new uint[256];
 
            if (!reflectInput)
            {
                uint crc = 0x80000000u;
 
                for (int i = 1; i < 256; i <<= 1)
                {
                    if ((crc & 0x80000000u) != 0)
                    {
                        crc = (crc << 1) ^ polynomial;
                    }
                    else
                    {
                        crc <<= 1;
                    }
 
                    for (int j = 0; j < i; j++)
                    {
                        table[i + j] = crc ^ table[j];
                    }
                }
            }
            else
            {
                for (int i = 1; i < 256; i++)
                {
                    uint r = ReverseBits((uint)i);
 
                    const uint LastBit = 0x80000000u;
 
                    for (int j = 0; j < 8; j++)
                    {
                        if ((r & LastBit) != 0)
                        {
                            r = (r << 1) ^ polynomial;
                        }
                        else
                        {
                            r <<= 1;
                        }
                    }
 
                    table[i] = ReverseBits(r);
                }
            }
 
            return table;
        }
 
        private sealed class ReflectedTableBasedCrc32 : Crc32ParameterSet
        {
            private readonly uint[] _lookupTable;
 
            internal ReflectedTableBasedCrc32(uint polynomial, uint initialValue, uint finalXorValue)
                : base(polynomial, initialValue, finalXorValue, reflectValues: true)
            {
                _lookupTable = GenerateLookupTable(polynomial, reflectInput: true);
            }
 
            internal override uint Update(uint value, ReadOnlySpan<byte> source)
            {
                uint[] lookupTable = _lookupTable;
                uint crc = value;
 
                Debug.Assert(lookupTable.Length == 256);
 
                foreach (byte dataByte in source)
                {
                    byte idx = (byte)(crc ^ dataByte);
                    crc = lookupTable[idx] ^ (crc >> 8);
                }
 
                return crc;
            }
        }
 
        private sealed class ForwardTableBasedCrc32 : Crc32ParameterSet
        {
            private readonly uint[] _lookupTable;
 
            internal ForwardTableBasedCrc32(uint polynomial, uint initialValue, uint finalXorValue)
                : base(polynomial, initialValue, finalXorValue, reflectValues: false)
            {
                _lookupTable = GenerateLookupTable(polynomial, reflectInput: false);
            }
 
            internal override uint Update(uint value, ReadOnlySpan<byte> source)
            {
                uint[] lookupTable = _lookupTable;
                uint crc = value;
 
                Debug.Assert(lookupTable.Length == 256);
 
                foreach (byte dataByte in source)
                {
                    byte idx = (byte)((crc >> 24) ^ dataByte);
                    crc = lookupTable[idx] ^ (crc << 8);
                }
 
                return crc;
            }
        }
    }
}