aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/util/crc.cpp
blob: 2f69da49eda53d7ec123c82c6a16b34daebcf031 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/util/crc.h>

namespace vespalib {

uint32_t            crc_32_type::_crc[256];
crc_32_type::CrcTableInit crc_32_type::_crcTableInit;

uint32_t crc_32_type::crc(const void * src, size_t sz)
{
    const uint8_t *v = static_cast<const uint8_t *>(src);
    uint32_t c(uint32_t(-1));

    for (size_t i(0); i < sz; i++ ) {
        c = (c >> 8) ^ _crc[ uint8_t(c ^ v[i]) ];
    }

    return c ^ (uint32_t(-1));
}

void crc_32_type::process_bytes(const void *start, size_t sz)
{
    const uint8_t *v = static_cast<const uint8_t *>(start);
    uint32_t c(_c);

    for (size_t i(0); i < sz; i++ ) {
        c = (c >> 8) ^ _crc[ uint8_t(c ^ v[i]) ];
    }
    _c = c;
}

crc_32_type::CrcTableInit::CrcTableInit()
{
    Bits::forceInitNow();
    uint8_t  dividend = 0;
    do {
        _crc[Bits::reverse(dividend)] = crc(dividend);
    } while ( ++dividend );
}

uint32_t crc_32_type::CrcTableInit::crc(uint8_t dividend)
{
    const uint32_t fast_hi_bit = 1ul << 31;
    const uint8_t  byte_hi_bit = 1u << 7;
    uint32_t remainder = 0;

    // go through all the dividend's bits
    for ( uint8_t mask = byte_hi_bit ; mask ; mask >>= 1 ) {
        // check if divisor fits
        if ( dividend & mask ) {
            remainder ^= fast_hi_bit;
        }

        // do polynominal division
        if ( remainder & fast_hi_bit ) {
            remainder <<= 1;
            remainder ^= 0x04C11DB7;
        } else {
            remainder <<= 1;
        }
    }
    return Bits::reverse( remainder );
}

}