Completed
Push — master ( a018f1...1aa741 )
by Philip
02:43
created

AbstractCRC::generateTable()   A

Complexity

Conditions 6
Paths 13

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 33
rs 9.0111
c 0
b 0
f 0
cc 6
nc 13
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PBurggraf\CRC;
6
7
/**
8
 * @author Philip Burggraf <[email protected]>
9
 */
10
abstract class AbstractCRC
11
{
12
    /**
13
     * @var int
14
     */
15
    protected $poly;
16
17
    /**
18
     * @var int
19
     */
20
    protected $init;
21
22
    /**
23
     * @var bool
24
     */
25
    protected $reverseIn;
26
27
    /**
28
     * @var bool
29
     */
30
    protected $reverseOut;
31
32
    /**
33
     * @var int
34
     */
35
    protected $xorOut;
36
37
    /**
38
     * @var array
39
     */
40
    protected $lookupTable;
41
42
    /**
43
     * @var int
44
     */
45
    protected $bitLength;
46
47
    /**
48
     * @param string $buffer
49
     *
50
     * @return int
51
     */
52
    public function calculate(string $buffer): int
53
    {
54
        $bufferLength = \strlen($buffer);
55
56
        $mask = (((1 << ($this->bitLength - 1)) - 1) << 1) | 1;
57
        $highBit = 1 << ($this->bitLength - 1);
58
59
        $crc = $this->init;
60
61
        for ($iterator = 0; $iterator < $bufferLength; ++$iterator) {
62
            $character = \ord($buffer[$iterator]);
63
            if ($this->reverseIn) {
64
                $character = $this->binaryReverse($character, 8);
65
            }
66
67
            for ($j = 0x80; $j; $j >>= 1) {
68
                $bit = $crc & $highBit;
69
                $crc <<= 1;
70
71
                if ($character & $j) {
72
                    $bit ^= $highBit;
73
                }
74
75
                if ($bit) {
76
                    $crc ^= $this->poly;
77
                }
78
            }
79
        }
80
81
        if ($this->reverseOut) {
82
            $crc = $this->binaryReverse($crc, $this->bitLength);
83
        }
84
85
        $crc ^= $this->xorOut;
86
87
        return $crc & $mask;
88
    }
89
90
    /**
91
     * @param int $polynomial
92
     *
93
     * @return array
94
     */
95
    protected function generateTable(int $polynomial): array
96
    {
97
        $tableSize = 256;
98
99
        $mask = (((1 << ($this->bitLength - 1)) - 1) << 1) | 1;
100
        $highBit = 1 << ($this->bitLength - 1);
101
102
        $crctab = [];
103
104
        for ($i = 0; $i < $tableSize; ++$i) {
105
            $crc = $i;
106
            if ($this->reverseIn) {
107
                $crc = $this->binaryReverse($crc, 8);
108
            }
109
110
            $crc <<= $this->bitLength - 8;
111
112
            for ($j = 0; $j < 8; ++$j) {
113
                $bit = $crc & $highBit;
114
                $crc <<= 1;
115
                if ($bit) {
116
                    $crc ^= $polynomial;
117
                }
118
            }
119
120
            if ($this->reverseOut) {
121
                $crc = $this->binaryReverse($crc, $this->bitLength);
122
            }
123
            $crc &= $mask;
124
            $crctab[] = $crc;
125
        }
126
127
        return $crctab;
128
    }
129
130
    /**
131
     * @param int $binaryInput
132
     * @param int $bitlen
133
     *
134
     * @return int
135
     */
136
    protected function binaryReverse(int $binaryInput, int $bitlen): int
137
    {
138
        $cloneBits = $binaryInput;
139
        $binaryInput = 0;
140
        $count = 0;
141
142
        while ($count < $bitlen) {
143
            ++$count;
144
            $binaryInput <<= 1;
145
            $binaryInput |= ($cloneBits & 0x1);
146
            $cloneBits >>= 1;
147
        }
148
149
        return $binaryInput;
150
    }
151
}
152