Skip to content

Commit

Permalink
Crc32: use slice-by-8 algorithm for faster calculation, default to in…
Browse files Browse the repository at this point in the history
…ternal crc32
  • Loading branch information
selmf committed May 1, 2022
1 parent e6fb85e commit efabf3d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
* Create CMake config-files for downstream integration
* New ar_entry_get_raw_name function for getting raw zip filenames (usefull for faulty zip archives with non-spec filename encodings)
* Support for Loongson CPUs (Liu Xiang)
* Faster crc32 based on Intel slice-by-8 algorithm

### Changed
* Update LZMA SDK code to version 21.07
* Restore limited support for 7z archive extraction (using an embedded subset of LZMA SDK)
* Convert source to LF line endings
* Increase UNARR_API_VERSION to 110
* Use internal crc32 implementation by default

### Fixed
* Fixed a possible memleak in rar filter code found by clang static analyzer
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ option(ENABLE_7Z "Build with 7z support" OFF)
option(USE_SYSTEM_BZ2 "Build with system bzip2 if possible" ON)
option(USE_SYSTEM_LZMA "Build with system lzma/xz if possible" ON)
option(USE_SYSTEM_ZLIB "Build with system zlib if possible" ON)
option(USE_ZLIB_CRC "Use zlib crc32" OFF)


# Build target
add_library(unarr
Expand Down
63 changes: 49 additions & 14 deletions common/crc32.c
Original file line number Diff line number Diff line change
@@ -1,34 +1,69 @@
/* Copyright 2015 the unarr project authors (see AUTHORS file).
/* Copyright 2022 the unarr project authors (see AUTHORS file).
License: LGPLv3 */

#include "unarr-imp.h"

#ifndef HAVE_ZLIB
#if !defined HAVE_ZLIB || !defined USE_ZLIB_CRC

/*
crc32 calculation based on Intel slice-by-8 algorithm with lookup-table generation code
adapted from https://gnunet.org/svn/gnunet/src/util/crypto_crc.c (public domain) */

/* code adapted from https://gnunet.org/svn/gnunet/src/util/crypto_crc.c (public domain) */
static inline uint32_t uint32le(const uint8_t *data) { return data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; }

static bool crc_table_ready = false;
static uint32_t crc_table[256];
static uint32_t crc_table[8][256];

uint32_t ar_crc32(uint32_t crc32, const unsigned char *data, size_t data_len)
uint32_t ar_crc32(uint32_t crc32, const uint8_t * data, size_t data_len)
{
if (!crc_table_ready) {
uint32_t i, j;

static const uint32_t crc_poly = 0xEDB88320;

uint32_t h = 1;
crc_table[0] = 0;
for (i = 128; i; i >>= 1) {
h = (h >> 1) ^ ((h & 1) ? 0xEDB88320 : 0);
for (j = 0; j < 256; j += 2 * i) {
crc_table[i + j] = crc_table[j] ^ h;
crc_table[0][0] = 0;

for (unsigned int i = 128; i; i >>= 1) {
h = (h >> 1) ^ ((h & 1) ? crc_poly : 0);
for (unsigned int j = 0; j < 256; j += 2 * i) {
crc_table[0][i+j] = crc_table[0][j] ^ h;
}
}

for (unsigned int i = 0; i < 256; i++) {
for (unsigned int j = 1; j < 8; j++) {
crc_table[j][i] = (crc_table[j-1][i] >> 8) ^ crc_table[0][crc_table[j-1][i] & 0xFF];
}
}

crc_table_ready = true;
}

crc32 = crc32 ^ 0xFFFFFFFF;
crc32 ^= 0xFFFFFFFF;

while (data_len >= 8) {

uint32_t tmp = crc32 ^ uint32le(data);

crc32 = crc_table[7][ tmp & 0xFF ] ^
crc_table[6][(tmp >> 8) & 0xFF ] ^
crc_table[5][(tmp >> 16) & 0xFF ] ^
crc_table[4][ tmp >> 24 ];

tmp = uint32le(data + 4);

crc32 ^= crc_table[3][tmp & 0xFF] ^
crc_table[2][(tmp >> 8) & 0xFF] ^
crc_table[1][(tmp >> 16) & 0xFF] ^
crc_table[0][ tmp >> 24 ];

data += 8;
data_len -= 8;
}

while (data_len-- > 0) {
crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ *data++) & 0xFF];
crc32 = (crc32 >> 8) ^ crc_table[0][(crc32 ^ *data++) & 0xFF];
}

return crc32 ^ 0xFFFFFFFF;
}

Expand Down

0 comments on commit efabf3d

Please sign in to comment.