CRC 计算模板适用于除 CRC8 之外的所有类型
CRC calculation template works for all types except CRC8
我不知道在这里问这个问题是否合适,还是应该在 codereview 上问。不管怎样,我写了下面的代码来计算各种类型的CRC。它的 CRC16、CRC32 和 CRC64 结果与在线实现匹配(例如 here and here). But for CRC8, the results don't match no matter have I set the parameters. I am not an expert in details of cyclic redundancy check, and just have read a part of the wikipedia article. Can anyone tell me what is wrong with my code?
#include <cstdio>
#include <string>
#include <stdint.h>
namespace crc
{
namespace templates
{
template <typename T> struct crcdata
{
T number = 0;
std::string toHex(void)
{
std::string s(2 * sizeof(T), '0');
for (T n = number, i = s.size(); n; n >>= 4)
s[--i] += (n & 0xF) > 9 ? (n % 16 - 9) | 16 : n % 16;
return s;
}
};
template <typename T, T polynomial, T init_cr, T final_cr>
class general_crc
{
public:
inline general_crc()
{
static T table[256];
/// build CRC lookup table. Skip the loop if already evaluated
for (int i = 0, b = 0; i < 256 && !table[255]; b = 8, i++)
{
table[i] = i;
while (b--) table[i] = (table[i] >> 1) ^ (table[i] & 1 ? polynomial : 0);
}
this->result.number = init_cr;
this->crc_table = (T const*)(void*)&table[0];
}
virtual ~general_crc(){}
private:
T const* crc_table;
crcdata <T> result;
void crc_calc(const void* buf, size_t size)
{
uint8_t* p = (uint8_t*)buf;
while (size--)
this->result.number = this->crc_table[(this->result.number ^ *p++) & 0xFF] ^ (this->result.number >> 8);
}
public:
/// crc of string
static crcdata <T> calculate(const std::string& s)
{
general_crc cr;
cr.crc_calc(s.c_str(), s.size());
cr.result.number ^= final_cr;
return cr.result;
}
};
}
typedef templates::general_crc <uint8_t, 0xAB, 0, 0> CRC8;
typedef templates::general_crc <uint16_t, 0xA001, 0, 0> CRC16;
typedef templates::general_crc <uint32_t, 0xEDB88320U, 0xFFFFFFFFU, 0xFFFFFFFFU> CRC32;
typedef templates::general_crc <uint64_t, 0xC96C5795D7870F42LLU, ~0LLU, ~0LLU> CRC64;
}
#include <iostream>
int main()
{
std::string test = "This is a test!!";
std::cout << crc::CRC8::calculate(test).toHex() << '\n';
std::cout << crc::CRC16::calculate(test).toHex() << '\n';
std::cout << crc::CRC32::calculate(test).toHex() << '\n';
std::cout << crc::CRC64::calculate(test).toHex() << '\n';
return 0;
}
代码和结果都没有问题。您认为您应该得到什么,为什么?
我不知道在这里问这个问题是否合适,还是应该在 codereview 上问。不管怎样,我写了下面的代码来计算各种类型的CRC。它的 CRC16、CRC32 和 CRC64 结果与在线实现匹配(例如 here and here). But for CRC8, the results don't match no matter have I set the parameters. I am not an expert in details of cyclic redundancy check, and just have read a part of the wikipedia article. Can anyone tell me what is wrong with my code?
#include <cstdio>
#include <string>
#include <stdint.h>
namespace crc
{
namespace templates
{
template <typename T> struct crcdata
{
T number = 0;
std::string toHex(void)
{
std::string s(2 * sizeof(T), '0');
for (T n = number, i = s.size(); n; n >>= 4)
s[--i] += (n & 0xF) > 9 ? (n % 16 - 9) | 16 : n % 16;
return s;
}
};
template <typename T, T polynomial, T init_cr, T final_cr>
class general_crc
{
public:
inline general_crc()
{
static T table[256];
/// build CRC lookup table. Skip the loop if already evaluated
for (int i = 0, b = 0; i < 256 && !table[255]; b = 8, i++)
{
table[i] = i;
while (b--) table[i] = (table[i] >> 1) ^ (table[i] & 1 ? polynomial : 0);
}
this->result.number = init_cr;
this->crc_table = (T const*)(void*)&table[0];
}
virtual ~general_crc(){}
private:
T const* crc_table;
crcdata <T> result;
void crc_calc(const void* buf, size_t size)
{
uint8_t* p = (uint8_t*)buf;
while (size--)
this->result.number = this->crc_table[(this->result.number ^ *p++) & 0xFF] ^ (this->result.number >> 8);
}
public:
/// crc of string
static crcdata <T> calculate(const std::string& s)
{
general_crc cr;
cr.crc_calc(s.c_str(), s.size());
cr.result.number ^= final_cr;
return cr.result;
}
};
}
typedef templates::general_crc <uint8_t, 0xAB, 0, 0> CRC8;
typedef templates::general_crc <uint16_t, 0xA001, 0, 0> CRC16;
typedef templates::general_crc <uint32_t, 0xEDB88320U, 0xFFFFFFFFU, 0xFFFFFFFFU> CRC32;
typedef templates::general_crc <uint64_t, 0xC96C5795D7870F42LLU, ~0LLU, ~0LLU> CRC64;
}
#include <iostream>
int main()
{
std::string test = "This is a test!!";
std::cout << crc::CRC8::calculate(test).toHex() << '\n';
std::cout << crc::CRC16::calculate(test).toHex() << '\n';
std::cout << crc::CRC32::calculate(test).toHex() << '\n';
std::cout << crc::CRC64::calculate(test).toHex() << '\n';
return 0;
}
代码和结果都没有问题。您认为您应该得到什么,为什么?