#include <stdio.h>
#include <string.h>
typedef unsigned int uint;
typedef unsigned char byte;
void init_crc32( void );
void init_crc32_merge( void );
uint crc32_merge( uint crc1, uint crc2, uint len2 );
uint crc32_update( uint x, byte c );
uint strcrc( char* s ) { uint x; for( x=0; *s++; x=crc32_update(x,s[-1]) ); return x; }
int main( void ) {
init_crc32();
init_crc32_merge();
char str1[] = "Hello";
char str2[] = " World!!!";
char str3[256] = "";
strcat(str3,str1);
strcat(str3,str2);
uint c1 = strcrc(str1), l1 = strlen(str1);
uint c2 = strcrc(str2), l2 = strlen(str2);
uint c3 = strcrc(str3), l3 = strlen(str3);
printf( "CRC32('%s')=%08X\n", str1, c1 );
printf( "CRC32('%s')=%08X\n", str2, c2 );
printf( "CRC32('%s')=%08X\n", str3, c3 );
printf( "crc32_merge(%08X,%08X,%i)=%08X\n", c1,c2,l2, crc32_merge(c1,c2,l2) );
}
uint CRCTab[256];
void init_crc32( void ) {
uint i, j, c;
for( i=0; i<256; i++ ) {
for( c=i,j=0; j<8; j++ ) c=(c&1) ? (c>>1)^0xEDB88320L : (c>>1);
CRCTab[i^0xFF] = c ^ 0xFF000000;
}
}
uint crc32_update( uint x, byte c ) { return CRCTab[byte(x)^c] ^ (x>>8); }
enum{ CRC_LEN=32 };
uint crc_mul( uint crc, uint (&mat)[CRC_LEN] ) {
uint i, out=0;
// for( i=0; i<32; i++ ) if( crc&(1<<i) ) out ^= mat[i];
for( i=0; crc; i++,crc>>=1 ) if( crc&1 ) out ^= mat[i];
return out;
}
void crc_set( uint (&out)[CRC_LEN], uint (&inp)[CRC_LEN] ) {
for( uint i=0; i<CRC_LEN; i++ ) out[i]=inp[i];
}
void crc_sqr( uint (&mat)[CRC_LEN] ) {
uint i, square[CRC_LEN];
for( i=0; i<CRC_LEN; i++ ) square[i] = crc_mul( mat[i], mat );
crc_set( mat, square );
}
uint crc_pad[CRC_LEN][CRC_LEN];
void init_crc32_merge( void ) {
uint i,mat[CRC_LEN];
// matrix for adding 1 zero bit to crc
mat[0] = 0xEDB88320; // CRC32 polynomial
for( i=1; i<CRC_LEN; i++ ) mat[i] = 1<<(i-1);
crc_sqr(mat); // 2 bits
crc_sqr(mat); // 4 bits
crc_sqr(mat); // 8 bits
for( i=0; i<CRC_LEN; i++ ) crc_set(crc_pad[i],mat), crc_sqr(mat);
}
uint crc32_merge( uint crc1, uint crc2, uint len2 ) {
// for( uint i=0; i<CRC_LEN; i++ ) if( len2 & (1<<i) ) crc1=crc_mul(crc1,crc_pad[i]);
for( uint i=0; len2; i++,len2>>=1 ) if( len2&1 ) crc1=crc_mul(crc1,crc_pad[i]);
return crc1 ^ crc2;
}
CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RyaW5nLmg+Cgp0eXBlZGVmIHVuc2lnbmVkIGludCB1aW50Owp0eXBlZGVmIHVuc2lnbmVkIGNoYXIgYnl0ZTsKCnZvaWQgaW5pdF9jcmMzMiggdm9pZCApOwp2b2lkIGluaXRfY3JjMzJfbWVyZ2UoIHZvaWQgKTsKdWludCBjcmMzMl9tZXJnZSggdWludCBjcmMxLCB1aW50IGNyYzIsIHVpbnQgbGVuMiApOwoKdWludCBjcmMzMl91cGRhdGUoIHVpbnQgeCwgYnl0ZSBjICk7CnVpbnQgc3RyY3JjKCBjaGFyKiBzICkgeyB1aW50IHg7IGZvciggeD0wOyAqcysrOyB4PWNyYzMyX3VwZGF0ZSh4LHNbLTFdKSApOyByZXR1cm4geDsgfQoKaW50IG1haW4oIHZvaWQgKSB7CiAgaW5pdF9jcmMzMigpOwogIGluaXRfY3JjMzJfbWVyZ2UoKTsKCiAgY2hhciBzdHIxW10gPSAiSGVsbG8iOwogIGNoYXIgc3RyMltdID0gIiBXb3JsZCEhISI7CiAgY2hhciBzdHIzWzI1Nl0gPSAiIjsKICBzdHJjYXQoc3RyMyxzdHIxKTsKICBzdHJjYXQoc3RyMyxzdHIyKTsKCiAgdWludCBjMSA9IHN0cmNyYyhzdHIxKSwgbDEgPSBzdHJsZW4oc3RyMSk7CiAgdWludCBjMiA9IHN0cmNyYyhzdHIyKSwgbDIgPSBzdHJsZW4oc3RyMik7CiAgdWludCBjMyA9IHN0cmNyYyhzdHIzKSwgbDMgPSBzdHJsZW4oc3RyMyk7CgogIHByaW50ZiggIkNSQzMyKCclcycpPSUwOFhcbiIsIHN0cjEsIGMxICk7CiAgcHJpbnRmKCAiQ1JDMzIoJyVzJyk9JTA4WFxuIiwgc3RyMiwgYzIgKTsKICBwcmludGYoICJDUkMzMignJXMnKT0lMDhYXG4iLCBzdHIzLCBjMyApOwoKICBwcmludGYoICJjcmMzMl9tZXJnZSglMDhYLCUwOFgsJWkpPSUwOFhcbiIsIGMxLGMyLGwyLCBjcmMzMl9tZXJnZShjMSxjMixsMikgKTsKCn0KCnVpbnQgQ1JDVGFiWzI1Nl07Cgp2b2lkIGluaXRfY3JjMzIoIHZvaWQgKSB7CiAgdWludCBpLCBqLCBjOwogIGZvciggaT0wOyBpPDI1NjsgaSsrICkgewogICAgZm9yKCBjPWksaj0wOyBqPDg7IGorKyApIGM9KGMmMSkgPyAoYz4+MSleMHhFREI4ODMyMEwgOiAoYz4+MSk7CiAgICBDUkNUYWJbaV4weEZGXSA9IGMgXiAweEZGMDAwMDAwOwogIH0KfQoKdWludCBjcmMzMl91cGRhdGUoIHVpbnQgeCwgYnl0ZSBjICkgeyByZXR1cm4gQ1JDVGFiW2J5dGUoeCleY10gXiAoeD4+OCk7IH0KCmVudW17IENSQ19MRU49MzIgfTsKCnVpbnQgY3JjX211bCggdWludCBjcmMsIHVpbnQgKCZtYXQpW0NSQ19MRU5dICkgewogIHVpbnQgaSwgb3V0PTA7Ci8vICBmb3IoIGk9MDsgaTwzMjsgaSsrICkgaWYoIGNyYyYoMTw8aSkgKSBvdXQgXj0gbWF0W2ldOwogIGZvciggaT0wOyBjcmM7IGkrKyxjcmM+Pj0xICkgaWYoIGNyYyYxICkgb3V0IF49IG1hdFtpXTsKICByZXR1cm4gb3V0Owp9Cgp2b2lkIGNyY19zZXQoIHVpbnQgKCZvdXQpW0NSQ19MRU5dLCB1aW50ICgmaW5wKVtDUkNfTEVOXSApIHsKICBmb3IoIHVpbnQgaT0wOyBpPENSQ19MRU47IGkrKyApIG91dFtpXT1pbnBbaV07Cn0KCnZvaWQgY3JjX3NxciggdWludCAoJm1hdClbQ1JDX0xFTl0gKSB7CiAgdWludCBpLCBzcXVhcmVbQ1JDX0xFTl07CiAgZm9yKCBpPTA7IGk8Q1JDX0xFTjsgaSsrICkgc3F1YXJlW2ldID0gY3JjX211bCggbWF0W2ldLCBtYXQgKTsKICBjcmNfc2V0KCBtYXQsIHNxdWFyZSApOwp9Cgp1aW50IGNyY19wYWRbQ1JDX0xFTl1bQ1JDX0xFTl07Cgp2b2lkIGluaXRfY3JjMzJfbWVyZ2UoIHZvaWQgKSB7CiAgdWludCBpLG1hdFtDUkNfTEVOXTsKICAvLyBtYXRyaXggZm9yIGFkZGluZyAxIHplcm8gYml0IHRvIGNyYwogIG1hdFswXSA9IDB4RURCODgzMjA7IC8vIENSQzMyIHBvbHlub21pYWwKICBmb3IoIGk9MTsgaTxDUkNfTEVOOyBpKysgKSBtYXRbaV0gPSAxPDwoaS0xKTsKICBjcmNfc3FyKG1hdCk7IC8vIDIgYml0cwogIGNyY19zcXIobWF0KTsgLy8gNCBiaXRzCiAgY3JjX3NxcihtYXQpOyAvLyA4IGJpdHMKICBmb3IoIGk9MDsgaTxDUkNfTEVOOyBpKysgKSBjcmNfc2V0KGNyY19wYWRbaV0sbWF0KSwgY3JjX3NxcihtYXQpOwp9Cgp1aW50IGNyYzMyX21lcmdlKCB1aW50IGNyYzEsIHVpbnQgY3JjMiwgdWludCBsZW4yICkgewovLyAgZm9yKCB1aW50IGk9MDsgaTxDUkNfTEVOOyBpKysgKSBpZiggbGVuMiAmICgxPDxpKSApIGNyYzE9Y3JjX211bChjcmMxLGNyY19wYWRbaV0pOwogIGZvciggdWludCBpPTA7IGxlbjI7IGkrKyxsZW4yPj49MSApIGlmKCBsZW4yJjEgKSBjcmMxPWNyY19tdWwoY3JjMSxjcmNfcGFkW2ldKTsKICByZXR1cm4gY3JjMSBeIGNyYzI7Cn0KCgo=