Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通用CRC(8/16/32/64)组合实现_C#_Checksum_Crc_Crc16 - Fatal编程技术网

C# 通用CRC(8/16/32/64)组合实现

C# 通用CRC(8/16/32/64)组合实现,c#,checksum,crc,crc16,C#,Checksum,Crc,Crc16,此问题的旧标题:CRC16联合收割机实施与CRC32联合收割机实施之间的差异 我正在尝试实现CRC16联合收割机实现,类似于CRC32联合收割机实现。我使用的是CRC-CCITT(首字母:0xFFFF,多边形:0x1021),如上所述 我阅读并试图理解本文中描述的CRC32_Combine实现,但我还没有完全理解它。我已经为CRC16联合收割机做了一个C#实现,只是将32x32矩阵修改为16x16,我不确定还有更多。我应该得到以下值,但我没有得到这些值: Msg1 : "123" CRC-16-

此问题的旧标题:CRC16联合收割机实施与CRC32联合收割机实施之间的差异

我正在尝试实现CRC16联合收割机实现,类似于CRC32联合收割机实现。我使用的是CRC-CCITT(首字母:0xFFFF,多边形:0x1021),如上所述

我阅读并试图理解本文中描述的CRC32_Combine实现,但我还没有完全理解它。我已经为CRC16联合收割机做了一个C#实现,只是将32x32矩阵修改为16x16,我不确定还有更多。我应该得到以下值,但我没有得到这些值:

Msg1 : "123" CRC-16-CCITT : 0x5bce
Msg2 : "456789" CRC-16-CCITT : 0x6887
Combined Msg1 + Msg2 : "123456789" CRC-16-CCITT should be "0x29B1".
But what I got with my code below is "0x64d8". 
C#中的ZLib代码:

const UInt16 poly16Reverse=0x8408;
常数Int16 GF2U尺寸=16;
专用静态UInt16 gf2矩阵次数(UInt16[]mat,UInt16 vec)
{
UInt16总和=0;
int-matIndex=0;
而(向量>0)
{
如果((vec&1)>0)
{
总和^=材料[matIndex];
}
vec>>=1;
matIndex++;
}
回报金额;
}
专用静态空隙gf2_矩阵_平方(UInt16[]平方,UInt16[]垫)
{
对于(int n=0;n0)
{
crc1=gf2×矩阵×次(奇数,crc1);
}
lenOfCrc2>>=1;
//如果没有设置更多位,则完成
}而(lenOfCrc2!=0);
//返回组合CRC
crc1^=crc2;
返回crc1;
}

任何之前有CRC16联合收割机实现的人都会大有裨益!

结果
0x29b1
表示“false”CCITT CRC-16。该CRC使用未反射的多项式,因此您将使用
0x1021
。请参阅。您还需要更改零运算符的初始化,并说明CRC的初始化

以下代码(C)概括了各种CRC的组合:

/* crccomb.c -- generalized combination of CRCs
 * Copyright (C) 2015 Mark Adler
 * Version 1.1  29 Apr 2015  Mark Adler
 */

/*
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the author be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Mark Adler
  madler@alumni.caltech.edu
 */

/*
   zlib provides a fast operation to combine the CRCs of two sequences of bytes
   into a single CRC, which is the CRC of the two sequences concatenated.  That
   operation requires only the two CRC's and the length of the second sequence.
   The routine in zlib only works on the particular CRC-32 used by zlib.  The
   code provided here generalizes that operation to apply to a wide range of
   CRCs.  The CRC is specified in a series of #defines, based on the
   parameterization found in Ross William's excellent CRC tutorial here:

      http://www.ross.net/crc/download/crc_v3.txt

   A comprehensive catalogue of known CRCs, their parameters, check values, and
   references can be found here:

      http://reveng.sourceforge.net/crc-catalogue/all.htm
 */

#include <stddef.h>
#include <stdint.h>
#define local static

/*
   CRC definition: WIDTH is the degree of the CRC polynomial, and so is the
   number of bits in the CRC.  crc_t is an unsigned integer type of at least
   WIDTH bits.  FMT is used to printf() a CRC value.  #define REFLECT if the
   CRC is reflected (i.e. both refin and refout are true).  Otherwise the CRC
   is considered to be normally ordered (refin and refout are both false).
   POLY is the CRC polynomial, bit-reversed if REFLECT is #defined.  INIT is
   the initial register value.  The final register value is exclusive-ored with
   XOROUT.  CHECK is the CRC of the nine bytes "123456789" (in ASCII).

   crc_general_combine() supports CRCs for which refin and refout are the same.
   That is the case for the vast majority of CRCs.  There is only one CRC in
   the catalogue linked above for which that is not the case (CRC-12/3GPP).
 */

/* Examples of a few CRCs are shown here for illustration and testing.  To
   compile this code, activate one of the definitions below with a #define. */

#define CRC16FALSE

/* CRC-6 CDMA2000-A */
#ifdef CRC6CDMA
#  define WIDTH 6
   typedef unsigned crc_t;
#  define FMT "0x%02x"
#  define POLY 0x27
#  define INIT 0x3f
#  define XOROUT 0
#  define CHECK 0x0d
#endif

/* CRC-8 ITU */
#ifdef CRC8ITU
#  define WIDTH 8
   typedef unsigned crc_t;
#  define FMT "0x%02x"
#  define POLY 7
#  define INIT 0
#  define XOROUT 0x55
#  define CHECK 0xa1
#endif

/* CRC-16 CCITT-False */
#ifdef CRC16FALSE
#  define WIDTH 16
   typedef unsigned crc_t;
#  define FMT "0x%04x"
#  define POLY 0x1021
#  define INIT 0xffff
#  define XOROUT 0
#  define CHECK 0x29b1
#endif

/* CRC-16 CCITT (also known as KERMIT) */
#ifdef CRC16TRUE
#  define WIDTH 16
   typedef unsigned crc_t;
#  define FMT "0x%04x"
#  define POLY 0x8408
#  define INIT 0
#  define REFLECT
#  define XOROUT 0
#  define CHECK 0x2189
#endif

/* CRC-32 (standard CRC used by zip, gzip, others) */
#ifdef CRC32
#  define WIDTH 32
   typedef unsigned long crc_t;
#  define FMT "0x%08lx"
#  define POLY 0xedb88320
#  define INIT 0xffffffff
#  define REFLECT
#  define XOROUT 0xffffffff
#  define CHECK 0xcbf43926
#endif

/* CRC-64 XZ (used by the xz compression utility) */
#ifdef CRC64XZ
#  define WIDTH 64
   typedef unsigned long long crc_t;
#  define FMT "0x%016llx"
#  define POLY 0xc96c5795d7870f42
#  define INIT 0xffffffffffffffff
#  define REFLECT
#  define XOROUT 0xffffffffffffffff
#  define CHECK 0x995dc9bbdf1939fa
#endif

/* Multiply the GF(2) vector vec by the GF(2) matrix mat, returning the
   resulting vector.  The vector is stored as bits in a crc_t.  The matrix is
   similarly stored with each column as a crc_t, where the number of columns is
   at least enough to cover the position of the most significant 1 bit in the
   vector (so a dimension parameter is not needed). */
local inline crc_t gf2_matrix_times(const crc_t *mat, crc_t vec)
{
    crc_t sum;

    sum = 0;
    while (vec) {
        if (vec & 1)
            sum ^= *mat;
        vec >>= 1;
        mat++;
    }
    return sum;
}

/* Multiply the matrix mat by itself, returning the result in square.  WIDTH is
   the dimension of the matrices, i.e., the number of bits in each crc_t
   (rows), and the number of crc_t's (columns). */
local void gf2_matrix_square(crc_t *square, const crc_t *mat)
{
    int n;

    for (n = 0; n < WIDTH; n++)
        square[n] = gf2_matrix_times(mat, mat[n]);
}

/* Combine the CRCs of two successive sequences, where crc1 is the CRC of the
   first sequence of bytes, crc2 is the CRC of the immediately following
   sequence of bytes, and len2 is the length of the second sequence.  The CRC
   of the combined sequence is returned. */
local crc_t crc_general_combine(crc_t crc1, crc_t crc2, uintmax_t len2)
{
    int n;
    crc_t col;
    crc_t even[WIDTH];          /* even-power-of-two zeros operator */
    crc_t odd[WIDTH];           /* odd-power-of-two zeros operator */

    /* degenerate case (also disallow negative lengths if type changed) */
    if (len2 <= 0)
        return crc1;

    /* exclusive-or the result with len2 zeros applied to the CRC of an empty
       sequence */
    crc1 ^= INIT ^ XOROUT;

    /* construct the operator for one zero bit and put in odd[] */
#ifdef REFLECT
    odd[0] = POLY;                /* polynomial */
    col = 1;
    for (n = 1; n < WIDTH; n++) {
        odd[n] = col;
        col <<= 1;
    }
#else
    col = 2;
    for (n = 0; n < WIDTH - 1; n++) {
        odd[n] = col;
        col <<= 1;
    }
    odd[n] = POLY;                /* polynomial */
#endif

    /* put operator for two zero bits in even[] */
    gf2_matrix_square(even, odd);

    /* put operator for four zero bits in odd[] */
    gf2_matrix_square(odd, even);

    /* apply len2 zeros to crc1 (first square will put the operator for eight
       zero bits == one zero byte, in even[]) */
    do {
        /* apply zeros operator for this bit of len2 */
        gf2_matrix_square(even, odd);
        if (len2 & 1)
            crc1 = gf2_matrix_times(even, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
        if (len2 == 0)
            break;

        /* another iteration of the loop with odd[] and even[] swapped */
        gf2_matrix_square(odd, even);
        if (len2 & 1)
            crc1 = gf2_matrix_times(odd, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
    } while (len2 != 0);

    /* return combined crc */
    crc1 ^= crc2;
    return crc1;
}

#ifdef TEST

/* Test crc_general_combine() for the defined CRC.  The last two CRC values
   printed should be equal. */

/* Update a general, parameterized CRC.  (See the parameter definitions above.)
   crc_general() updates crc with the sequence buf[0..len-1], and returns the
   updated crc.  If buf is NULL, crc_general() returns the initial value to use
   for crc.  A CRC calculation of a long sequence can be broken into pieces:

   crc = crc_general(0, NULL, 0);   // initial value
   crc = crc_general(crc, buf_1, len_1);
   ...
   crc = crc_general(crc, buf_n, len_n);

   The final value of crc is then the CRC of the sequence buf_1, ..., buf_n.

   crc_general() is a simple, bit-wise implementation for testing purposes.  A
   CRC routine for production use would instead use table-driven approaches to
   compute the CRC using byte-wise or word-wise algorithms, for speed. */
crc_t crc_general(crc_t crc, unsigned char *buf, size_t len)
{
    int k;

    if (buf == NULL)
        return INIT ^ XOROUT;
    crc ^= XOROUT;
#ifdef REFLECT
    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
    }
#elif WIDTH >= 8
#  define TOP ((crc_t)1 << (WIDTH - 1))
#  define MASK ((TOP << 1) - 1)
    while (len--) {
        crc ^= *buf++ << (WIDTH - 8);
        for (k = 0; k < 8; k++)
            crc = crc & TOP ? (crc << 1) ^ POLY : crc << 1;
    }
    crc &= MASK;
#else
#  define POLY8 (POLY << (8 - WIDTH))
    crc <<= 8 - WIDTH;
    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 0x80 ? (crc << 1) ^ POLY8 : crc << 1;
    }
    crc &= 0xff;
    crc >>= 8 - WIDTH;
#endif
    return crc ^ XOROUT;
}

#include <stdio.h>

int main(void)
{
    crc_t init, crc1, crc2, crc3, crc4;

    init = crc_general(0, NULL, 0);
    crc1 = crc_general(init, (unsigned char *)"123", 3);
    crc2 = crc_general(init, (unsigned char *)"456789", 6);
    crc3 = crc_general(init, (unsigned char *)"123456789", 9);
    crc4 = crc_general_combine(crc1, crc2, 6);
    printf(FMT ", " FMT ", " FMT ", " FMT ", " FMT "\n",
           crc1, crc2, crc3, crc4, (crc_t)CHECK);
    if (crc3 != (crc_t)CHECK || crc4 != crc3)
        puts("mismatch!");
    return 0;
}

#endif
/*crccomb.c——CRC的广义组合
*版权所有(C)2015 Mark Adler
*版本1.1 2015年4月29日Mark Adler
*/
/*
本软件按“原样”提供,无任何明示或暗示
在任何情况下,作者都不对任何损害负责
由于使用本软件而产生的。
允许任何人出于任何目的使用本软件,
包括商业应用程序,并对其进行修改和重新发布
自由,受以下限制:
1.不得歪曲本软件的来源;您不得
声称您编写了原始软件。如果您使用此软件
在产品中,产品文档中的确认是
感谢,但不是必需的。
2.更改的源版本必须清楚地标记为这样,并且不得
被误传为原始软件。
3.本通知不得从任何来源分发中删除或更改。
马克艾德勒
madler@alumni.caltech.edu
*/
/*
zlib提供了一种快速操作来组合两个字节序列的CRC
转换为单个CRC,即两个串联序列的CRC
该操作只需要两个CRC和第二个序列的长度。
zlib中的例程仅在zlib使用的特定CRC-32上工作
这里提供的代码概括了该操作,以应用于广泛的应用程序
CRC。CRC在一系列#定义中指定,基于
Ross William优秀的CRC教程中的参数化:
http://www.ross.net/crc/download/crc_v3.txt
已知CRC、其参数、检查值和
可在此处找到参考资料:
http://reveng.sourceforge.net/crc-catalogue/all.htm
*/
#包括
#包括
#定义局部静态
/*
CRC定义:宽度是CRC多项式的次数,所以是
CRC中的位数。CRC\u t是至少为的无符号整数类型
宽度位。FMT用于打印f()一个CRC值。#定义
CRC被反映(即refin和refout均为真)。否则CRC
被视为正常有序(refin和refout均为false)。
POLY是CRC多项式,如果定义了反射,则位反转。INIT是
初始寄存器值。最终寄存器值与或异或
CHECK是九个字节“123456789”(ASCII)的CRC。
crc_general_combine()支持refin和refout相同的crc。
这是绝大多数CRC的情况,在中国只有一个CRC
上面链接的目录并非如此(CRC-12/3GPP)。
*/
/*此处显示了一些CRC的示例,用于说明和测试。至
编译此代码,使用#define激活以下定义之一*/
#定义CRC16FALSE
/*CRC-6 CDMA2000-A*/
#ifdef CRC6CDMA
#定义宽度6
typedef无符号crc\t;
#定义FMT“0x%02x”
#定义多边形0x27
#定义初始化0x3f
#定义XOROUT 0
#定义检查0x0d
#恩迪夫
/*CRC-8国际电联*/
#ifdef CRC8ITU
#定义宽度8
typedef无符号crc\t;
#定义FMT“0x%02x”
#定义多边形7
#定义初始化0
#定义XOROUT 0x55
#定义检查0xa1
#恩迪夫
/*CRC-16 CCITT错误*/
#ifdef CRC16FALSE
#定义宽度16
typedef无符号crc\t;
#定义FMT“0x%04x”
#定义多边形0x1021
#定义INIT 0xffff
#定义XOROUT 0
#定义检查0x29b1
#恩迪夫
/*CRC-16CCITT(
/* crccomb.c -- generalized combination of CRCs
 * Copyright (C) 2015 Mark Adler
 * Version 1.1  29 Apr 2015  Mark Adler
 */

/*
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the author be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Mark Adler
  madler@alumni.caltech.edu
 */

/*
   zlib provides a fast operation to combine the CRCs of two sequences of bytes
   into a single CRC, which is the CRC of the two sequences concatenated.  That
   operation requires only the two CRC's and the length of the second sequence.
   The routine in zlib only works on the particular CRC-32 used by zlib.  The
   code provided here generalizes that operation to apply to a wide range of
   CRCs.  The CRC is specified in a series of #defines, based on the
   parameterization found in Ross William's excellent CRC tutorial here:

      http://www.ross.net/crc/download/crc_v3.txt

   A comprehensive catalogue of known CRCs, their parameters, check values, and
   references can be found here:

      http://reveng.sourceforge.net/crc-catalogue/all.htm
 */

#include <stddef.h>
#include <stdint.h>
#define local static

/*
   CRC definition: WIDTH is the degree of the CRC polynomial, and so is the
   number of bits in the CRC.  crc_t is an unsigned integer type of at least
   WIDTH bits.  FMT is used to printf() a CRC value.  #define REFLECT if the
   CRC is reflected (i.e. both refin and refout are true).  Otherwise the CRC
   is considered to be normally ordered (refin and refout are both false).
   POLY is the CRC polynomial, bit-reversed if REFLECT is #defined.  INIT is
   the initial register value.  The final register value is exclusive-ored with
   XOROUT.  CHECK is the CRC of the nine bytes "123456789" (in ASCII).

   crc_general_combine() supports CRCs for which refin and refout are the same.
   That is the case for the vast majority of CRCs.  There is only one CRC in
   the catalogue linked above for which that is not the case (CRC-12/3GPP).
 */

/* Examples of a few CRCs are shown here for illustration and testing.  To
   compile this code, activate one of the definitions below with a #define. */

#define CRC16FALSE

/* CRC-6 CDMA2000-A */
#ifdef CRC6CDMA
#  define WIDTH 6
   typedef unsigned crc_t;
#  define FMT "0x%02x"
#  define POLY 0x27
#  define INIT 0x3f
#  define XOROUT 0
#  define CHECK 0x0d
#endif

/* CRC-8 ITU */
#ifdef CRC8ITU
#  define WIDTH 8
   typedef unsigned crc_t;
#  define FMT "0x%02x"
#  define POLY 7
#  define INIT 0
#  define XOROUT 0x55
#  define CHECK 0xa1
#endif

/* CRC-16 CCITT-False */
#ifdef CRC16FALSE
#  define WIDTH 16
   typedef unsigned crc_t;
#  define FMT "0x%04x"
#  define POLY 0x1021
#  define INIT 0xffff
#  define XOROUT 0
#  define CHECK 0x29b1
#endif

/* CRC-16 CCITT (also known as KERMIT) */
#ifdef CRC16TRUE
#  define WIDTH 16
   typedef unsigned crc_t;
#  define FMT "0x%04x"
#  define POLY 0x8408
#  define INIT 0
#  define REFLECT
#  define XOROUT 0
#  define CHECK 0x2189
#endif

/* CRC-32 (standard CRC used by zip, gzip, others) */
#ifdef CRC32
#  define WIDTH 32
   typedef unsigned long crc_t;
#  define FMT "0x%08lx"
#  define POLY 0xedb88320
#  define INIT 0xffffffff
#  define REFLECT
#  define XOROUT 0xffffffff
#  define CHECK 0xcbf43926
#endif

/* CRC-64 XZ (used by the xz compression utility) */
#ifdef CRC64XZ
#  define WIDTH 64
   typedef unsigned long long crc_t;
#  define FMT "0x%016llx"
#  define POLY 0xc96c5795d7870f42
#  define INIT 0xffffffffffffffff
#  define REFLECT
#  define XOROUT 0xffffffffffffffff
#  define CHECK 0x995dc9bbdf1939fa
#endif

/* Multiply the GF(2) vector vec by the GF(2) matrix mat, returning the
   resulting vector.  The vector is stored as bits in a crc_t.  The matrix is
   similarly stored with each column as a crc_t, where the number of columns is
   at least enough to cover the position of the most significant 1 bit in the
   vector (so a dimension parameter is not needed). */
local inline crc_t gf2_matrix_times(const crc_t *mat, crc_t vec)
{
    crc_t sum;

    sum = 0;
    while (vec) {
        if (vec & 1)
            sum ^= *mat;
        vec >>= 1;
        mat++;
    }
    return sum;
}

/* Multiply the matrix mat by itself, returning the result in square.  WIDTH is
   the dimension of the matrices, i.e., the number of bits in each crc_t
   (rows), and the number of crc_t's (columns). */
local void gf2_matrix_square(crc_t *square, const crc_t *mat)
{
    int n;

    for (n = 0; n < WIDTH; n++)
        square[n] = gf2_matrix_times(mat, mat[n]);
}

/* Combine the CRCs of two successive sequences, where crc1 is the CRC of the
   first sequence of bytes, crc2 is the CRC of the immediately following
   sequence of bytes, and len2 is the length of the second sequence.  The CRC
   of the combined sequence is returned. */
local crc_t crc_general_combine(crc_t crc1, crc_t crc2, uintmax_t len2)
{
    int n;
    crc_t col;
    crc_t even[WIDTH];          /* even-power-of-two zeros operator */
    crc_t odd[WIDTH];           /* odd-power-of-two zeros operator */

    /* degenerate case (also disallow negative lengths if type changed) */
    if (len2 <= 0)
        return crc1;

    /* exclusive-or the result with len2 zeros applied to the CRC of an empty
       sequence */
    crc1 ^= INIT ^ XOROUT;

    /* construct the operator for one zero bit and put in odd[] */
#ifdef REFLECT
    odd[0] = POLY;                /* polynomial */
    col = 1;
    for (n = 1; n < WIDTH; n++) {
        odd[n] = col;
        col <<= 1;
    }
#else
    col = 2;
    for (n = 0; n < WIDTH - 1; n++) {
        odd[n] = col;
        col <<= 1;
    }
    odd[n] = POLY;                /* polynomial */
#endif

    /* put operator for two zero bits in even[] */
    gf2_matrix_square(even, odd);

    /* put operator for four zero bits in odd[] */
    gf2_matrix_square(odd, even);

    /* apply len2 zeros to crc1 (first square will put the operator for eight
       zero bits == one zero byte, in even[]) */
    do {
        /* apply zeros operator for this bit of len2 */
        gf2_matrix_square(even, odd);
        if (len2 & 1)
            crc1 = gf2_matrix_times(even, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
        if (len2 == 0)
            break;

        /* another iteration of the loop with odd[] and even[] swapped */
        gf2_matrix_square(odd, even);
        if (len2 & 1)
            crc1 = gf2_matrix_times(odd, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
    } while (len2 != 0);

    /* return combined crc */
    crc1 ^= crc2;
    return crc1;
}

#ifdef TEST

/* Test crc_general_combine() for the defined CRC.  The last two CRC values
   printed should be equal. */

/* Update a general, parameterized CRC.  (See the parameter definitions above.)
   crc_general() updates crc with the sequence buf[0..len-1], and returns the
   updated crc.  If buf is NULL, crc_general() returns the initial value to use
   for crc.  A CRC calculation of a long sequence can be broken into pieces:

   crc = crc_general(0, NULL, 0);   // initial value
   crc = crc_general(crc, buf_1, len_1);
   ...
   crc = crc_general(crc, buf_n, len_n);

   The final value of crc is then the CRC of the sequence buf_1, ..., buf_n.

   crc_general() is a simple, bit-wise implementation for testing purposes.  A
   CRC routine for production use would instead use table-driven approaches to
   compute the CRC using byte-wise or word-wise algorithms, for speed. */
crc_t crc_general(crc_t crc, unsigned char *buf, size_t len)
{
    int k;

    if (buf == NULL)
        return INIT ^ XOROUT;
    crc ^= XOROUT;
#ifdef REFLECT
    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
    }
#elif WIDTH >= 8
#  define TOP ((crc_t)1 << (WIDTH - 1))
#  define MASK ((TOP << 1) - 1)
    while (len--) {
        crc ^= *buf++ << (WIDTH - 8);
        for (k = 0; k < 8; k++)
            crc = crc & TOP ? (crc << 1) ^ POLY : crc << 1;
    }
    crc &= MASK;
#else
#  define POLY8 (POLY << (8 - WIDTH))
    crc <<= 8 - WIDTH;
    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 0x80 ? (crc << 1) ^ POLY8 : crc << 1;
    }
    crc &= 0xff;
    crc >>= 8 - WIDTH;
#endif
    return crc ^ XOROUT;
}

#include <stdio.h>

int main(void)
{
    crc_t init, crc1, crc2, crc3, crc4;

    init = crc_general(0, NULL, 0);
    crc1 = crc_general(init, (unsigned char *)"123", 3);
    crc2 = crc_general(init, (unsigned char *)"456789", 6);
    crc3 = crc_general(init, (unsigned char *)"123456789", 9);
    crc4 = crc_general_combine(crc1, crc2, 6);
    printf(FMT ", " FMT ", " FMT ", " FMT ", " FMT "\n",
           crc1, crc2, crc3, crc4, (crc_t)CHECK);
    if (crc3 != (crc_t)CHECK || crc4 != crc3)
        puts("mismatch!");
    return 0;
}

#endif