CRC通用計算類

/*前段時間在做項目中用到了CRC循環校驗,在網上查了很多資料,但是都很零亂;
本人作了相關整理,並對常用的循環冗餘校驗進行了封裝,形成本文件。
在這裏感謝網絡上提供相關資料的朋友們,關於他們的名字在這裏我無法一一列舉,再次向他們表示感謝!*/
/*以下代碼的計算思想適用於所有CRC校驗算法。
64位以上的由於ulong已經無法表示了,所以沒有實現。但是思想也是一樣的。不過64位以上可以使用.net裏面的
別的hash:比如md5等算法.
主要參考地址:[url]http://www.wiki.cn/wiki/Cyclic_redundancy_check[/url]
[url]http://www.zorc.breitbandkatze.de/crc.html[/url]   [url]http://www.zorc.breitbandkatze.de/crctester.c[/url]
*/
/*
需要注意的是:即使都是同樣位數的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;
  }
 };
}}}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章