CRC通用计算类
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://happyoldbear.blog.51cto.com/231048/43405 |
/*前段时间在做项目中用到了CRC循环校验,在网上查了很多资料,但是都很零乱;
本人作了相关整理,并对常用的循环冗余校验进行了封装,形成本文件。 在这里感谢网络上提供相关资料的朋友们,关于他们的名字在这里我无法一一列举,再次向他们表示感谢!*/ /*以下代码的计算思想适用于所有CRC校验算法。
64位以上的由于ulong已经无法表示了,所以没有实现。但是思想也是一样的。不过64位以上可以使用.net里面的 别的hash:比如md5等算法. 主要参考地址:http://www.wiki.cn/wiki/Cyclic_redundancy_check http://www.zorc.breitbandkatze.de/crc.html http://www.zorc.breitbandkatze.de/crctester.c */ /*
需要注意的是:即使都是同样位数的crc校验,多项式也可以不同。即使多项式相同,初值,末值xor,是否反转等设置也可以不同 所以在通信的双方需要约定好。 以下的具体crc子类只是我能找到的一些常用的crc约定。 哪位兄弟有具体的crc约定,可以告知我进行扩展。 */ //* 采用了泛型定义基类,基类是一个通用的计算CRC的方法,定义具体的类时只需要设置好CRC设置即可。
//* 本来想用c#写模版代码,可是C#编译器居然先检查 >> & 计算,说T无法进行这些操作,无法编译通过。 //* 所以改成用c++实现.所以c#还是只能称为泛型,而c++才能称为模板 //**********************************************************************************************************/ //crc的设置.选用一个crc算法时,子类必须设置这些值
int m_order;//CRC多项式的阶数 1到64 T m_polynom;//CRC多项式 T m_crcinit;//CRC的初值 T m_crcxor;//和最终结果xor的值 int m_refin;//0或者1,表示输入在处理前是否反转 int m_refout;//0或者1,表示输出结果是否反转 int m_direct;//0或者1,1表示直接使用m_crcinit CRC的原理,俺这里就不说了。大家可以参考网上的很多资料。
下面是源代码:
#pragma once
using namespace System;
using namespace System::Collections::Generic; using namespace System::Diagnostics; #pragma warning(disable:4333)
namespace Hob{namespace Toolbox{namespace Classes
{ /// <summary> /// CRC基类,抽象类,模版类.注:T只能是long,int,byte...等 /// </summary> template<typename T> public ref class CRC abstract { public: CRC() { //初始化crc算法设置 InitCRCSettings(); CRC_Table=nullptr; CRC_Mask = ( ( ( (T)1<<(m_order-1) )-1 )<<1 )|1; CRC_HighBit =( (T)1<<(m_order-1) ); CheckSettings();//检查设置 //初始化CRC Table InitCRCTable(); //计算初值 Count_CRCInit_direct(); } private: /// <summary> /// 初始化CRC table /// </summary> void InitCRCTable() { if(CRC_Table!=nullptr) return; CRC_Table = gcnew array<T>(256);
int i,j;
T bit, crc; for(i=0;i<256;i++) { crc=i; if (m_refin) crc=reflect(crc, 8); crc<<= m_order-8; for (j=0; j<8; j++)
{ bit = crc & CRC_HighBit; crc<<= 1; if (bit) crc^= m_polynom; } if (m_refin) crc = reflect(crc, m_order);
crc&= CRC_Mask; CRC_Table[i]= crc; } } //将一个值crc的低bitnum位进行反转.
T reflect (T crc, int bitnum) { // reflects the lower 'bitnum' bits of 'crc' T i, j=1, crcout=0; for (i=( (T)1<<(bitnum-1) ); i; i>>=1) { if (crc & i) crcout|=j; j<<= 1; } return crcout; } //计算直接初值
void Count_CRCInit_direct() { if(m_direct) //direct { CRCInit_direct=m_crcinit; return; } T crc = m_crcinit;
for (int i=0; i<m_order; i++) { T bit = crc & CRC_HighBit; crc<<= 1; if (bit) crc^= m_polynom; } CRCInit_direct = crc & CRC_Mask; }
protected: //初始化crc设置 virtual void InitCRCSettings() abstract; //检查crc设置 void CheckSettings() { if(m_order<1 || m_order>64) Debug::Fail("ERROR,invalid order!"); if (m_polynom != (m_polynom & CRC_Mask)) Debug::Fail("ERROR,invalid polynom!"); if (m_crcinit != (m_crcinit & CRC_Mask)) Debug::Fail("ERROR,invalid crcinit!"); if (m_crcxor != (m_crcxor & CRC_Mask)) Debug::Fail("ERROR,invalid crcxor!"); } private: array<T>^ CRC_Table;//crc table T CRC_Mask;//mask值,比如crc8为0xff T CRC_HighBit;//CRC的最高位 比如crc8为0x80 //直接用来计算crc的初值 m_direct=1时就是m_crcinit m_direct时进行Count_CRCInit_direct计算 T CRCInit_direct; protected: //crc的设置.选用一个crc算法时,子类必须设置这些值 int m_order;//CRC多项式的阶数 1到64 T m_polynom;//CRC多项式 T m_crcinit;//CRC的初值 T m_crcxor;//和最终结果xor的值 int m_refin;//0或者1,表示输入在处理前是否反转 int m_refout;//0或者1,表示输出结果是否反转 int m_direct;//0或者1,1表示直接使用m_crcinit public: /// <summary> /// 计算得到CRC值 /// </summary> T GetCRC(array<Byte>^ pBuffer, int Length) { T crc = CRCInit_direct; if (m_refin) crc = reflect(crc, m_order); Byte ValueByte;
for (int i=0;i<Length;i++) { ValueByte=pBuffer[i]; if(!m_refin) crc = (crc << 8) ^ CRC_Table[(int) (( (crc>>(m_order-8) ) & 0xff) ^ ValueByte)]; else crc = (crc >> 8) ^ CRC_Table[(int) ((crc & 0xff) ^ ValueByte)]; } if (m_refout^m_refin)
crc = reflect(crc, m_order); crc = (crc ^m_crcxor) & CRC_Mask;
return crc;
} }; //宏
#define IMPLEMENT_GETCRC(_GETCRC_RETURN) \ _GETCRC_RETURN GetCRC(array<Byte>^ pBuffer, int Length) \ { \ return CRC::GetCRC(pBuffer, Length); \ } /// <summary>
/// CRC-8 名称:CRC-8-ATM /// 0x7=x8 + x2 + x + 1 /// </summary> public ref class CRC8_ATM:CRC<Byte> { public: IMPLEMENT_GETCRC(Byte) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 8; m_polynom = 0x7; m_crcinit = 0x0; m_crcxor = 0x0; m_refin = 0; m_refout= 0; m_direct=1; } }; /// <summary> /// CRC-8 名称:CRC-8-Dallas/Maxim /// 0x31=X(8)+X(5)+X(4)+X(0) /// </summary> public ref class CRC8_Dallas:CRC<Byte> { public: IMPLEMENT_GETCRC(Byte) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 8; m_polynom = 0x31; m_crcinit = 0x0; m_crcxor = 0x0; m_refin = 1; m_refout= 1; m_direct=1; } }; /// <summary>
/// CRC-16 名称:CRC-16-IBM,也即通常讲的CRC16 /// 0x8005=x16 + x15 + x2 + 1 /// </summary> public ref class CRC16:CRC<UInt16> { public: IMPLEMENT_GETCRC(UInt16) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 16; m_polynom = 0x8005; m_crcinit = 0x0; m_crcxor = 0x0; m_refin = 1; m_refout=1; m_direct=1; } }; /// <summary>
/// CRC-16-CCITT ,也即通常讲的CRC-CCITT /// 0x1021=x16 + x12 + x5 + 1 /// </summary> public ref class CRC16_CCITT:CRC<UInt16> { public: IMPLEMENT_GETCRC(UInt16) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 16; m_polynom = 0x1021; m_crcinit = 0xFFFF; m_crcxor = 0x0; m_refin = 0; m_refout=0; m_direct=1; } }; /// <summary>
/// CRC-16-XKERMIT,用于xmodem协议 /// 0x8408=x16+x15 + x10 + x3 /// </summary> public ref class CRC16_XKERMIT:CRC<UInt16> { public: IMPLEMENT_GETCRC(UInt16) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 16; m_polynom = 0x8408; m_crcinit = 0; m_crcxor = 0x0; m_refin = 1; m_refout=1; m_direct=1; } }; /// <summary>
/// CRC-32 名称:CRC-32-IEEE 802.3,也即通常的CRC32/FCS32 /// 0x04C11DB7 = x32 + x26 + x23 + x22 + x16 + x12 + /// x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 /// </summary> public ref class CRC32:CRC<UInt32> { public: IMPLEMENT_GETCRC(UInt32) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 32; m_polynom = 0x4c11db7; m_crcinit = 0xFFFFFFFF; m_crcxor = 0xFFFFFFFF; m_refin = 1; m_refout=1; m_direct=1; } }; /// <summary> /// CRC-64 CRC-64-ECMA-182 /// 0x42F0E1EBA9EA3693 = x^{64} + x^{62} + x^{57} + x^{55} + x^{54} + x^{53} + x^{52} + /// x^{47} + x^{46} + x^{45} + x^{40} + x^{39} + x^{38} + x^{37} + x^{35} /// + x^{33} +x^{32} + x^{31} + x^{29} + x^{27} + x^{24} + x^{23} + x^{22} + /// x^{21} + x^{19} + x^{17} + x^{13} + x^{12} + x^{10} + x^9 + x^7 + x^4 + x + 1 /// </summary> public ref class CRC64_ECMA:CRC<UInt64> { public: IMPLEMENT_GETCRC(UInt64) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 64; m_polynom = 0x42F0E1EBA9EA3693; m_crcinit=0xFFFFFFFFFFFFFFFF; m_crcxor=0xFFFFFFFFFFFFFFFF; m_refin = 0; m_refout = 0; m_direct = 1; } }; }}} 本文出自 “欢乐老熊” 博客,请务必保留此出处http://happyoldbear.blog.51cto.com/231048/43405 本文出自 51CTO.COM技术博客 |
附件下载:
源代码
源代码


lijun4183
博客统计信息
热门文章
最新评论
友情链接
