c_src/crc32c.c

// Copyright (c) 2026 Benoit Chesneau. Licensed under the MIT License.
// See the LICENSE file at the project root.

#include "crc32c.h"

#include <pthread.h>

#define POLY 0x82F63B78u  /* reflected form of 0x1EDC6F41 */

static uint32_t crc32c_table[256];
static pthread_once_t crc32c_table_once = PTHREAD_ONCE_INIT;

static void crc32c_table_build(void) {
    for (uint32_t i = 0; i < 256; i++) {
        uint32_t c = i;
        for (int j = 0; j < 8; j++) {
            c = (c & 1u) ? (POLY ^ (c >> 1)) : (c >> 1);
        }
        crc32c_table[i] = c;
    }
}

int erllama_crc32c_init(void) {
    /* pthread_once guarantees crc32c_table_build runs exactly once
     * across concurrent callers; subsequent calls are a single
     * relaxed atomic load on the once-control. The return is
     * propagated so the NIF load callback can refuse to attach a
     * NIF whose CRC table failed to initialise. */
    return pthread_once(&crc32c_table_once, crc32c_table_build);
}

uint32_t erllama_crc32c_update(uint32_t crc, const uint8_t *data, size_t len) {
    uint32_t c = ~crc;
    for (size_t i = 0; i < len; i++) {
        c = crc32c_table[(c ^ data[i]) & 0xFFu] ^ (c >> 8);
    }
    return ~c;
}