< Summary

Information
Class: Hash.Core.CRC64_ECMA
Assembly: Hash.Core
File(s): /home/runner/work/HashCalculator/HashCalculator/src/Hash.Core/CRC.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 147
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%

File(s)

/home/runner/work/HashCalculator/HashCalculator/src/Hash.Core/CRC.cs

#LineLine coverage
 1// Copyright © 2021-present Hibi_10000
 2//
 3// This file is part of HashCalculator program.
 4//
 5// This program is free software: you can redistribute it and/or modify
 6// it under the terms of the GNU General Public License as published by
 7// the Free Software Foundation, either version 3 of the License, or
 8// (at your option) any later version.
 9//
 10// This program is distributed in the hope that it will be useful,
 11// but WITHOUT ANY WARRANTY; without even the implied warranty of
 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 13// GNU General Public License for more details.
 14//
 15// You should have received a copy of the GNU General Public License
 16// along with this program. If not, see <http://www.gnu.org/licenses/>.
 17
 18using System;
 19using System.Buffers.Binary;
 20using System.IO.Hashing;
 21
 22namespace Hash.Core;
 23
 24public class CRC8_CCITT () : CRC(sizeof(byte), 0x07, 0x00, false);
 25public class CRC16_CCITT() : CRC(sizeof(ushort), 0x1021, 0x0000, true);
 26public class CRC16_IBM  () : CRC(sizeof(ushort), 0x8005, 0x0000, true);
 27public class CRC32      () : CRC(sizeof(uint), 0x04C11DB7, 0xffffffff, true);
 28public class CRC32C     () : CRC(sizeof(uint), 0x1EDC6F41, 0xffffffff, true);
 129public class CRC64_ECMA () : CRC(sizeof(ulong), 0x42F0E1EBA9EA3693, 0x0000000000000000, false);
 30public class CRC64_ISO  () : CRC(sizeof(ulong), 0x000000000000001B, 0xffffffffffffffff, true);
 31public class CRC64_XZ   () : CRC(sizeof(ulong), 0x42F0E1EBA9EA3693, 0xffffffffffffffff, true);
 32
 33public class CRC : NonCryptographicHashAlgorithm
 34{
 35    private ulong _hash;
 36    private readonly ulong[] _table;
 37    private readonly ulong _seed;
 38    private readonly bool _refOut;
 39    private readonly ulong _xorOut;
 40    private readonly int _size;
 41
 42    protected internal CRC(int size, ulong poly, ulong init, bool refInOut) : base(size)
 43    {
 44        _table = InitializeTable(size, poly, refInOut);
 45        _seed = init;
 46        _refOut = refInOut;
 47        _xorOut = init;
 48        _size = size;
 49        _hash = _seed;
 50    }
 51
 52    public override void Append(ReadOnlySpan<byte> source)
 53    {
 54        _hash = CalculateHash(_size, _table, _hash, _refOut, source);
 55    }
 56
 57    public override void Reset()
 58    {
 59        _hash = _seed;
 60    }
 61
 62    private static ulong[] InitializeTable(int size, ulong poly, bool refIn)
 63    {
 64        ulong[] table = new ulong[256]; //byte.MaxValue + 1
 65        if (refIn)
 66        {
 67            for (int i = 0; i < 256; i++)
 68            {
 69                ulong entry = (ulong)i;
 70                for (int j = 0; j < 8; j++)
 71                {
 72                    if ((entry & 1) != 0)
 73                        entry = (entry >> 1) ^ ReverseBits(poly, size * 8);
 74                    else
 75                        entry >>= 1;
 76                }
 77                table[i] = size == sizeof(byte) ? (byte)entry : entry;
 78            }
 79        }
 80        else
 81        {
 82            for (int i = 0; i < 256; i++)
 83            {
 84                ulong entry = size == sizeof(byte) ? (ulong)i : (ulong)i << 56;
 85                for (int j = 0; j < 8; j++)
 86                {
 87                    if ((entry & ReverseBits(1, size * 8)) != 0)
 88                        entry = (entry << 1) ^ poly;
 89                    else
 90                        entry <<= 1;
 91                }
 92                table[i] = size == sizeof(byte) ? (byte)entry : entry;
 93            }
 94        }
 95        return table;
 96    }
 97
 98    private static ulong ReverseBits(ulong source, int size)
 99    {
 100        ulong reverse = 0;
 101        for (int i = 0; i < size; i++)
 102        {
 103            reverse = (reverse << 1) | ((source >> i) & 1);
 104        }
 105        return reverse;
 106    }
 107
 108    private static ulong CalculateHash(int size, ulong[] table, ulong seed, bool refOut, ReadOnlySpan<byte> buffer)
 109    {
 110        ulong crc = seed;
 111        if (refOut)
 112        {
 113            foreach (byte bufferEntry in buffer)
 114            {
 115                crc = (crc >> 8) ^ table[(byte)(bufferEntry ^ crc)];
 116            }
 117        }
 118        else
 119        {
 120            foreach (byte bufferEntry in buffer)
 121            {
 122                crc = (crc << 8) ^ table[(byte)(bufferEntry ^ (size == sizeof(byte) ? crc : crc >> 56))];
 123            }
 124        }
 125        return crc;
 126    }
 127
 128    protected override void GetCurrentHashCore(Span<byte> destination)
 129    {
 130        ulong hash = _hash ^ _xorOut;
 131        switch (_size)
 132        {
 133            case sizeof(byte  ): //1  8
 134                destination[0] = (byte)hash;
 135                break;
 136            case sizeof(ushort): //2 16
 137                BinaryPrimitives.WriteUInt16BigEndian(destination, (ushort)hash);
 138                break;
 139            case sizeof(uint  ): //4 32
 140                BinaryPrimitives.WriteUInt32BigEndian(destination, (uint)  hash);
 141                break;
 142            case sizeof(ulong ): //8 64
 143                BinaryPrimitives.WriteUInt64BigEndian(destination,         hash);
 144                break;
 145        }
 146    }
 147}

Methods/Properties

.ctor()