unsigned long crc32(const unsigned char *p, unsigned int n) {
    unsigned long crc = 0xFFFFFFFFUL;
    while (n--) {
        crc ^= *p++;
        for (int k = 0; k < 8; k++) {
            crc = (crc >> 1) ^ (0xEDB88320UL & -(long)(crc & 1));
        }
    }
    return crc ^ 0xFFFFFFFFUL;
}
