AbstractCRC::binaryReverse()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 14
rs 9.9666
cc 2
nc 2
nop 2
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
    protected int $poly;
13
14
    protected int $init;
15
16
    protected bool $reverseIn;
17
18
    protected bool $reverseOut;
19
20
    protected int $xorOut;
21
22
    protected int $bitLength;
23
24
    public function calculate(string $buffer): int
25
    {
26
        $bufferLength = \strlen($buffer);
27
28
        $mask = (((1 << ($this->bitLength - 1)) - 1) << 1) | 1;
29
        $highBit = 1 << ($this->bitLength - 1);
30
31
        $crc = $this->init;
32
33
        for ($iterator = 0; $iterator < $bufferLength; ++$iterator) {
34
            $character = \ord($buffer[$iterator]);
35
            if ($this->reverseIn) {
36
                $character = $this->binaryReverse($character, 8);
37
            }
38
39
            for ($j = 0x80; $j; $j >>= 1) {
40
                $bit = $crc & $highBit;
41
                $crc <<= 1;
42
43
                if ($character & $j) {
44
                    $bit ^= $highBit;
45
                }
46
47
                if ($bit) {
48
                    $crc ^= $this->poly;
49
                }
50
            }
51
        }
52
53
        if ($this->reverseOut) {
54
            $crc = $this->binaryReverse($crc, $this->bitLength);
55
        }
56
57
        $crc ^= $this->xorOut;
58
59
        return $crc & $mask;
60
    }
61
62
    public function calculateWithTable(string $buffer, array $table): int
63
    {
64
        $bufferLength = \strlen($buffer);
65
66
        if (count($table) !== 256) {
67
            throw new \InvalidArgumentException('CRC lookup table not populated');
68
        }
69
70
        $mask = (((1 << ($this->bitLength - 1)) - 1) << 1) | 1;
71
        $highBit = 1 << ($this->bitLength - 1);
0 ignored issues
show
Unused Code introduced by
The assignment to $highBit is dead and can be removed.
Loading history...
72
73
        $crc = $this->init;
74
75
        for ($iterator = 0; $iterator < $bufferLength; ++$iterator) {
76
            $character = \ord($buffer[$iterator]);
77
            if ($this->reverseIn) {
78
                $character = $this->binaryReverse($character, 8);
79
            }
80
81
            $tableValue = $table[(($crc >> ($this->bitLength - 8)) ^ $character) & 0xFF];
82
83
            if (($this->bitLength - 8) !== 0) {
84
                $tableValue ^= ($crc << 8);
85
            }
86
87
            $crc = $tableValue;
88
            $crc &= $mask;
89
        }
90
91
        if ($this->reverseOut) {
92
            $crc = $this->binaryReverse($crc, $this->bitLength);
93
        }
94
95
        $crc ^= $this->xorOut;
96
97
        return $crc & $mask;
98
    }
99
100
    /**
101
     * @return int[]
102
     */
103
    public function populateTable(): array
104
    {
105
        $tableSize = 256;
106
107
        $mask = (((1 << ($this->bitLength - 1)) - 1) << 1) | 1;
108
        $highBit = 1 << ($this->bitLength - 1);
109
110
        $table = [];
111
112
        for ($iterator = 0; $iterator < $tableSize; ++$iterator) {
113
            $temp = 0;
114
            $a = ($iterator << ($this->bitLength - 8));
115
            for ($j = 0; $j < 8; ++$j) {
116
                if ((($temp ^ $a) & $highBit) !== 0) {
117
                    $temp = (($temp << 1) ^ $this->poly);
118
                } else {
119
                    $temp <<= 1;
120
                }
121
                $a <<= 1;
122
            }
123
            $table[$iterator] = $temp & $mask;
124
        }
125
126
        return $table;
127
    }
128
129
    protected function binaryReverse(int $binaryInput, int $bitlen): int
130
    {
131
        $cloneBits = $binaryInput;
132
        $binaryInput = 0;
133
        $count = 0;
134
135
        while ($count < $bitlen) {
136
            ++$count;
137
            $binaryInput <<= 1;
138
            $binaryInput |= ($cloneBits & 0x1);
139
            $cloneBits >>= 1;
140
        }
141
142
        return $binaryInput;
143
    }
144
}
145