POSIX cksum和Boost.CRC

时间:2013-04-06 15:49:08

标签: c++ boost posix crc

我正在尝试使用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

相关联

1 个答案:

答案 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

这是因为:

  • 规范未指定生成器的起始值,因此为0.
  • 根据规范的第4项,应补充输出值。通过将值与1进行异或来实现相同的结果。
  • 在任何地方都没有提到位反映,因此不会执行。

但是,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提供。

希望我帮助过。