我正在尝试使用Boost.CRC实现简单的POSIX cksum
。
我正在使用的代码相当于:
for(int i = 1; i<argc; ++i)
{
support::file current(argv[i], support::file::access::read);
size_t octets = 0;
boost::crc_32_type crc;
while(true)
{
size_t bytes_read = current.read_some(buffer_size, buffer);
octets += bytes_read;
crc.process_bytes(&buffer[0], bytes_read);
if(bytes_read < buffer_size)
break;
}
if(i>1)
support::print("\n");
support::print(boost::lexical_cast<string>(crc.checksum()) + " " + boost::lexical_cast<string>(octets) + " " + argv[i]);
}
support::file
是一个简单的fopen
/ fread
二进制文件I / O包装器,我成功地用于cat
实现。 support::print
提供与std::cout
相同的输出,但我需要它在Windows上可靠的非ASCII输出。
Boost标题包含:
typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc_32_type;
作为唯一的32位CRC typedef。它为空文件(cksum
)提供了错误的答案(使用GNUWin32 coreutils touch test && cksum test
检查)。我已经尝试使用上面的typedef并将0xFFFFFFFF
值中的一个或两个修改为0,我得到了一个空文件的正确结果,但是任何其他文件仍然会得到不同的结果。
Boost.CRC如何与POSIX cksum
specification?
答案 0 :(得分:1)
这不是你问题的真正答案,而是我所进行的调查结果。当我在VHDL中构建一个简单的以太网控制器实现时,我曾经很难与CRC斗争,我做意识到由于原因未知,实现有时会变化很大。
好的,我们开始吧。您在typedef
中找到的boost/crc.hpp
:
typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc_32_type;
是CRC生成器的简单声明,它将生成以太网的CRC。模板的参数如下:Bits
(生成器输出的位数),TruncPoly
(生成器使用的多项式),InitRem
(初始余数为在处理输入的第一个字节之前输入算法,FinalXor
(在处理输入的所有字节后,输出值应为XORed
的值),ReflectIn
和{ {1}}(如果输入字节和/或输出应该是位反射的,例如位0变为位7,依此类推)。以太网不仅要求使用给定的多项式计算输出,而且还需要您可以从该typedef读取的约束。
根据ReflectRem
的规范,CRC生成器的typedef应该如下所示:
cksum
这是因为:
但是,typedef crc_optimal<32, 0x04C11DB7, 0, 0xFFFFFFFF, false, false> cksum_crc_type;
与普通的CRC相比,存在一个显着差异:
(...)后跟一个或多个代表长度的八位字节 文件作为二进制值,最低有效八位字节。最小的 应使用能够表示该整数的八位字节数。
普通CRC生成器不考虑已处理的八位字节数。这也解释了为什么在处理零长度文件时获得了良好的结果,但在处理较大的文件时却是一个糟糕的结果。
不幸的是,我没有看到解决该问题的简单方法。我想你可以做的是以下列方式修改cksum
方法:
process_bytes
通过这样的实现,该方法给出与template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly,
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor,
bool ReflectIn, bool ReflectRem >
inline
void
BOOST_CRC_OPTIMAL_NAME::process_bytes
(
void const * buffer,
std::size_t byte_count
)
{
unsigned char const * const b = static_cast<unsigned char const *>(
buffer );
process_block( b, b + byte_count );
for(; byte_count; byte_count >>= 8)
rem_ = (rem_ << 8) ^ crc_table_type::table_[((rem_ >> 24) ^ byte_count) & 0xFF];
}
相同的结果。 cksum
循环由GNU coreutils提供。
希望我帮助过。