crctool.cs

来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 632 行 · 第 1/2 页

CS
632
字号
using System;

namespace Communication.IO.Tools
{
	/// <summary>
	/// Tool to calculate and add CRC codes to a string
	/// 
    /// ***************************************************************************
    /// Copyright 2003-2004 Thoraxcentrum, Erasmus MC, The Netherlands.
    /// 
	/// 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.
    /// 
    /// Orignaly written by Marcel de Wijs with help from a lot of others, 
    /// especially Stefan Nelwan
    /// 
    /// Edited by Maarten JB van Ettinger.
    /// 
    /// This code is for free. I ported it from several different sources to C#.
    /// 
    /// For comments: Marcel_de_Wijs@hotmail.com
    /// ***************************************************************************
    /// </summary>
	public class CRCTool
	{
        // 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit
        // 'polynom' is the CRC polynom without leading '1' bit
        // 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits
        // 'crcinit' is the initial CRC value belonging to that algorithm
        // 'crcxor' is the final XOR value
        // 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
        // 'refout' [0,1] specifies if the CRC will be reflected before XOR
        // Data character string
        // For CRC-CCITT : order = 16, direct=1, poly=0x1021, CRCinit = 0xFFFF, crcxor=0; refin =0, refout=0  
        // For CRC16:      order = 16, direct=1, poly=0x8005, CRCinit = 0x0, crcxor=0x0; refin =1, refout=1  
        // For CRC32:      order = 32, direct=1, poly=0x4c11db7, CRCinit = 0xFFFFFFFF, crcxor=0xFFFFFFFF; refin =1, refout=1  
        // Default : CRC-CCITT

        private int   order      = 16;
        private ulong polynom    = 0x1021;
        private int   direct     = 1;
        private ulong crcinit    = 0xFFFF;
        private ulong crcxor     = 0x0;
        private int   refin      = 0;
        private int   refout     = 0;
        
        private ulong crcmask;
        private ulong crchighbit;
        private ulong crcinit_direct;
        private ulong crcinit_nondirect;
        private ulong [] crctab = new ulong[256];

        // Enumeration used in the init function to specify which CRC algorithm to use
        public enum CRCCode{CRC_CCITT, CRC16, CRC32};

		public CRCTool()
		{
			// 
			// TODO: Add constructor logic here
			//
		}

        public void Init(CRCCode CodingType)
        {
            switch( CodingType )
            {
                case CRCCode.CRC_CCITT:
                    order = 16; direct=1; polynom=0x1021; crcinit = 0xFFFF; crcxor=0; refin =0; refout=0;
                    break;
                case CRCCode.CRC16:
                    order = 16; direct=1; polynom=0x8005; crcinit = 0x0; crcxor=0x0; refin =1; refout=1;  
                    break;
                case CRCCode.CRC32:
                    order = 32; direct=1; polynom=0x4c11db7; crcinit = 0xFFFFFFFF; crcxor=0xFFFFFFFF; refin =1; refout=1;  
                    break;
            }
            
            // Initialize all variables for seeding and builing based upon the given coding type
            // at first, compute constant bit masks for whole CRC and CRC high bit
            
            crcmask = ((((ulong)1<<(order-1))-1)<<1)|1;
            crchighbit = (ulong)1<<(order-1);

            // generate lookup table
            generate_crc_table();

            ulong bit, crc;
            int i;
            if ( direct == 0 ) 
            {
                crcinit_nondirect = crcinit;
                crc = crcinit;
                for (i=0; i<order; i++) 
                {
                    bit = crc & crchighbit;
                    crc<<= 1;
                    if ( bit != 0 ) 
                    {
                        crc^= polynom;
                    }
                }
                crc&= crcmask;
                crcinit_direct = crc;
            }
            else 
            {
                crcinit_direct = crcinit;
                crc = crcinit;
                for (i=0; i<order; i++) 
                {
                    bit = crc & 1;
                    if (bit != 0) 
                    {
                        crc^= polynom;
                    }
                    crc >>= 1;
                    if (bit != 0) 
                    {
                        crc|= crchighbit;
                    }
                }	
                crcinit_nondirect = crc;
            }
        }


        /// <summary>
        /// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
        /// you should use the table functions. Since they use precalculated values, which 
        /// saves some calculating.
        /// </summary>.
        public ulong crctablefast (byte[] p) 
        {
            // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
            // only usable with polynom orders of 8, 16, 24 or 32.
            ulong crc = crcinit_direct;
            if ( refin != 0 )
            {
                crc = reflect(crc, order);
            }
            if ( refin == 0 ) 
            {
                for ( int i = 0; i < p.Length; i++ )
                {
                    crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ p[i]];
                }
            }
            else 
            {
                for ( int i = 0; i < p.Length; i++ )
                {
                    crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ p[i]];
                }
            }
            if ( (refout^refin) != 0 ) 
            {
                crc = reflect(crc, order);
            }
            crc^= crcxor;
            crc&= crcmask;
            return(crc);
        }

		/// <summary>
		/// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
		/// you should use the table functions. Since they use precalculated values, which 
		/// saves some calculating.
		/// </summary>.
		public ulong crctablefast (byte[] p, int offset, int length) 
		{
			// Works like crctablefast(byte[] p), except you now calculate a CRC for a specific part of the byte array.

			// fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
			// only usable with polynom orders of 8, 16, 24 or 32.
			ulong crc = crcinit_direct;

			if (offset < 0)
				offset = 0;
			length += offset;
			if (length > p.Length)
				length = p.Length;

			if ( refin != 0 )
			{
				crc = reflect(crc, order);
			}
			if ( refin == 0 ) 
			{
				for ( int i = offset; i < length; i++ )
				{
					crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ p[i]];
				}
			}
			else 
			{
				for ( int i = offset; i < length; i++ )
				{
					crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ p[i]];
				}
			}
			if ( (refout^refin) != 0 ) 
			{
				crc = reflect(crc, order);
			}
			crc^= crcxor;
			crc&= crcmask;
			return(crc);
		}

        public ulong crctable (byte[] p) 
        {
            // normal lookup table algorithm with augmented zero bytes.
            // only usable with polynom orders of 8, 16, 24 or 32.
            ulong crc = crcinit_nondirect;
            if ( refin != 0 ) 
            {
                crc = reflect(crc, order);
            }
            if ( refin == 0 ) 
            {
                for ( int i = 0; i < p.Length; i++ )
                {
                    crc = ((crc << 8) | p[i]) ^ crctab[ (crc >> (order-8)) & 0xff ];
                }
            }
            else 
            {
                for ( int i = 0; i < p.Length; i++ )
                {
                    crc = (ulong)(( (int)(crc >> 8) | (p[i] << (order-8))) ^ (int)crctab[ crc & 0xff ]);
                }
            }
            if ( refin == 0 ) 
            {
                for ( int i = 0; i < order/8; i++ )
                {
                    crc = (crc << 8) ^ crctab[ (crc >> (order-8))  & 0xff];
                } 
            }
            else 
            {
                for ( int i = 0; i < order/8; i++ )
                {
                    crc = (crc >> 8) ^ crctab[crc & 0xff];
                } 
            }

            if ( (refout^refin) != 0 ) 
            {
                crc = reflect(crc, order);
            }
            crc^= crcxor;
            crc&= crcmask;

            return(crc);
        }

		// Works like crctable(byte[] p), except you now calculate a CRC for a specific part of the byte array.
		public ulong crctable (byte[] p, int offset, int length) 
		{
			// normal lookup table algorithm with augmented zero bytes.
			// only usable with polynom orders of 8, 16, 24 or 32.
			ulong crc = crcinit_nondirect;

			if (offset < 0)
				offset = 0;
			length += offset;
			if (length > p.Length)
				length = p.Length;

			if ( refin != 0 ) 
			{
				crc = reflect(crc, order);
			}
			if ( refin == 0 ) 
			{
				for ( int i = offset; i < length; i++ )
				{
					crc = ((crc << 8) | p[i]) ^ crctab[ (crc >> (order-8)) & 0xff ];
				}
			}
			else 
			{
				for ( int i = offset; i < length; i++ )
				{
					crc = (ulong)(( (int)(crc >> 8) | (p[i] << (order-8))) ^ (int)crctab[ crc & 0xff ]);
				}
			}
			if ( refin == 0 ) 
			{
				for ( int i = 0; i < order/8; i++ )
				{
					crc = (crc << 8) ^ crctab[ (crc >> (order-8))  & 0xff];
				} 
			}
			else 
			{
				for ( int i = 0; i < order/8; i++ )
				{
					crc = (crc >> 8) ^ crctab[crc & 0xff];
				} 
			}

			if ( (refout^refin) != 0 ) 
			{
				crc = reflect(crc, order);
			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?