1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpBinaryReader\Type; |
4
|
|
|
|
5
|
|
|
use PhpBinaryReader\BinaryReader; |
6
|
|
|
use PhpBinaryReader\BitMask; |
7
|
|
|
use PhpBinaryReader\Endian; |
8
|
|
|
|
9
|
|
View Code Duplication |
class Int32 implements TypeInterface |
|
|
|
|
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* @var string |
13
|
|
|
*/ |
14
|
|
|
private $endianBig = 'N'; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
private $endianLittle = 'V'; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Returns an Unsigned 32-bit Integer |
23
|
|
|
* |
24
|
|
|
* @param \PhpBinaryReader\BinaryReader $br |
25
|
|
|
* @param null $length |
26
|
|
|
* @return int |
27
|
|
|
* @throws \OutOfBoundsException |
28
|
|
|
*/ |
29
|
26 |
|
public function read(BinaryReader &$br, $length = null) |
30
|
|
|
{ |
31
|
26 |
|
if (!$br->canReadBytes(4)) { |
32
|
4 |
|
throw new \OutOfBoundsException('Cannot read 32-bit int, it exceeds the boundary of the file'); |
33
|
|
|
} |
34
|
|
|
|
35
|
22 |
|
$endian = $br->getEndian() == Endian::ENDIAN_BIG ? $this->endianBig : $this->endianLittle; |
36
|
22 |
|
$segment = $br->readFromHandle(4); |
37
|
|
|
|
38
|
22 |
|
$data = unpack($endian, $segment); |
39
|
22 |
|
$data = $data[1]; |
40
|
|
|
|
41
|
22 |
|
if ($br->getCurrentBit() != 0) { |
42
|
4 |
|
$data = $this->bitReader($br, $data); |
43
|
|
|
} |
44
|
|
|
|
45
|
22 |
|
return $data; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Returns a Signed 32-Bit Integer |
50
|
|
|
* |
51
|
|
|
* @param \PhpBinaryReader\BinaryReader $br |
52
|
|
|
* @return int |
53
|
|
|
*/ |
54
|
12 |
|
public function readSigned(&$br) |
55
|
|
|
{ |
56
|
12 |
|
$this->setEndianBig('l'); |
57
|
12 |
|
$this->setEndianLittle('l'); |
58
|
|
|
|
59
|
12 |
|
$value = $this->read($br); |
60
|
|
|
|
61
|
12 |
|
$this->setEndianBig('N'); |
62
|
12 |
|
$this->setEndianLittle('V'); |
63
|
|
|
|
64
|
12 |
|
if ($br->getMachineByteOrder() != Endian::ENDIAN_LITTLE && $br->getEndian() == Endian::ENDIAN_LITTLE) { |
65
|
2 |
|
$endian = new Endian(); |
66
|
|
|
|
67
|
2 |
|
return $endian->convert($value); |
68
|
|
|
} else { |
69
|
10 |
|
return $value; |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @param \PhpBinaryReader\BinaryReader $br |
75
|
|
|
* @param int $data |
76
|
|
|
* @return int |
77
|
|
|
*/ |
78
|
4 |
|
private function bitReader(&$br, $data) |
79
|
|
|
{ |
80
|
4 |
|
$bitmask = new BitMask(); |
81
|
4 |
|
$loMask = $bitmask->getMask($br->getCurrentBit(), BitMask::MASK_LO); |
82
|
4 |
|
$hiMask = $bitmask->getMask($br->getCurrentBit(), BitMask::MASK_HI); |
83
|
4 |
|
$hiBits = ($br->getNextByte() & $hiMask) << 24; |
84
|
4 |
|
$miBits = ($data & 0xFFFFFF00) >> (8 - $br->getCurrentBit()); |
85
|
4 |
|
$loBits = ($data & $loMask); |
86
|
4 |
|
$br->setNextByte($data & 0xFF); |
87
|
|
|
|
88
|
4 |
|
return $hiBits | $miBits | $loBits; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param string $endianBig |
93
|
|
|
*/ |
94
|
13 |
|
public function setEndianBig($endianBig) |
95
|
|
|
{ |
96
|
13 |
|
$this->endianBig = $endianBig; |
97
|
13 |
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @return string |
101
|
|
|
*/ |
102
|
1 |
|
public function getEndianBig() |
103
|
|
|
{ |
104
|
1 |
|
return $this->endianBig; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param string $endianLittle |
109
|
|
|
*/ |
110
|
13 |
|
public function setEndianLittle($endianLittle) |
111
|
|
|
{ |
112
|
13 |
|
$this->endianLittle = $endianLittle; |
113
|
13 |
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @return string |
117
|
|
|
*/ |
118
|
1 |
|
public function getEndianLittle() |
119
|
|
|
{ |
120
|
1 |
|
return $this->endianLittle; |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.