#include "zbuild.h"
#include "crc32_braid_p.h"
#include "crc32_braid_tbl.h"
#ifdef BRAID_W
# if BYTE_ORDER == LITTLE_ENDIAN
static uint32_t crc_word(z_word_t data) {
int k;
for (k = 0; k < BRAID_W; k++)
data = (data >> 8) ^ crc_table[data & 0xff];
return (uint32_t)data;
}
# elif BYTE_ORDER == BIG_ENDIAN
static z_word_t crc_word(z_word_t data) {
int k;
for (k = 0; k < BRAID_W; k++)
data = (data << 8) ^
crc_big_table[(data >> ((BRAID_W - 1) << 3)) & 0xff];
return data;
}
# endif
#endif
Z_INTERNAL uint32_t crc32_braid_internal(uint32_t c, const uint8_t *buf, size_t len) {
#ifdef BRAID_W
if (len >= BRAID_N * BRAID_W + BRAID_W - 1) {
size_t blks;
z_word_t const *words;
int k;
while (len && ((uintptr_t)buf & (BRAID_W - 1)) != 0) {
len--;
CRC_DO1;
}
blks = len / (BRAID_N * BRAID_W);
len -= blks * BRAID_N * BRAID_W;
words = (z_word_t const *)buf;
z_word_t crc0, word0, comb;
#if BRAID_N > 1
z_word_t crc1, word1;
#if BRAID_N > 2
z_word_t crc2, word2;
#if BRAID_N > 3
z_word_t crc3, word3;
#if BRAID_N > 4
z_word_t crc4, word4;
#if BRAID_N > 5
z_word_t crc5, word5;
#endif
#endif
#endif
#endif
#endif
crc0 = ZSWAPWORD(c);
#if BRAID_N > 1
crc1 = 0;
#if BRAID_N > 2
crc2 = 0;
#if BRAID_N > 3
crc3 = 0;
#if BRAID_N > 4
crc4 = 0;
#if BRAID_N > 5
crc5 = 0;
#endif
#endif
#endif
#endif
#endif
while (--blks) {
word0 = crc0 ^ words[0];
#if BRAID_N > 1
word1 = crc1 ^ words[1];
#if BRAID_N > 2
word2 = crc2 ^ words[2];
#if BRAID_N > 3
word3 = crc3 ^ words[3];
#if BRAID_N > 4
word4 = crc4 ^ words[4];
#if BRAID_N > 5
word5 = crc5 ^ words[5];
#endif
#endif
#endif
#endif
#endif
words += BRAID_N;
crc0 = BRAID_TABLE[0][word0 & 0xff];
#if BRAID_N > 1
crc1 = BRAID_TABLE[0][word1 & 0xff];
#if BRAID_N > 2
crc2 = BRAID_TABLE[0][word2 & 0xff];
#if BRAID_N > 3
crc3 = BRAID_TABLE[0][word3 & 0xff];
#if BRAID_N > 4
crc4 = BRAID_TABLE[0][word4 & 0xff];
#if BRAID_N > 5
crc5 = BRAID_TABLE[0][word5 & 0xff];
#endif
#endif
#endif
#endif
#endif
for (k = 1; k < BRAID_W; k++) {
crc0 ^= BRAID_TABLE[k][(word0 >> (k << 3)) & 0xff];
#if BRAID_N > 1
crc1 ^= BRAID_TABLE[k][(word1 >> (k << 3)) & 0xff];
#if BRAID_N > 2
crc2 ^= BRAID_TABLE[k][(word2 >> (k << 3)) & 0xff];
#if BRAID_N > 3
crc3 ^= BRAID_TABLE[k][(word3 >> (k << 3)) & 0xff];
#if BRAID_N > 4
crc4 ^= BRAID_TABLE[k][(word4 >> (k << 3)) & 0xff];
#if BRAID_N > 5
crc5 ^= BRAID_TABLE[k][(word5 >> (k << 3)) & 0xff];
#endif
#endif
#endif
#endif
#endif
}
}
comb = crc_word(crc0 ^ words[0]);
#if BRAID_N > 1
comb = crc_word(crc1 ^ words[1] ^ comb);
#if BRAID_N > 2
comb = crc_word(crc2 ^ words[2] ^ comb);
#if BRAID_N > 3
comb = crc_word(crc3 ^ words[3] ^ comb);
#if BRAID_N > 4
comb = crc_word(crc4 ^ words[4] ^ comb);
#if BRAID_N > 5
comb = crc_word(crc5 ^ words[5] ^ comb);
#endif
#endif
#endif
#endif
#endif
words += BRAID_N;
Assert(comb <= UINT32_MAX, "comb should fit in uint32_t");
c = (uint32_t)ZSWAPWORD(comb);
buf = (const unsigned char *)words;
}
#endif
while (len >= 8) {
len -= 8;
CRC_DO8;
}
while (len) {
len--;
CRC_DO1;
}
return c;
}
Z_INTERNAL uint32_t crc32_braid(uint32_t c, const uint8_t *buf, size_t len) {
c = (~c) & 0xffffffff;
c = crc32_braid_internal(c, buf, len);
return c ^ 0xffffffff;
}