Skip to content

Commit 23e08d5

Browse files
authored
Merge pull request #12 from nsknewbie/feature/float-reader
implemented 4-bytes floating-point reader
2 parents 55c1c2e + 4c014e0 commit 23e08d5

13 files changed

Lines changed: 230 additions & 23 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ Methods
5757

5858
**readInt32()** returns a 32-bit signed integer
5959

60+
**readSingle()** returns a 4-bytes floating-point
61+
6062
**readUBits($length)** returns a variable length of bits (unsigned)
6163

6264
**readBits($length)** returns a variable length of bits (signed)

src/BinaryReader.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpBinaryReader\Type\Int8;
99
use PhpBinaryReader\Type\Int16;
1010
use PhpBinaryReader\Type\Int32;
11+
use PhpBinaryReader\Type\Single;
1112
use PhpBinaryReader\Type\Str;
1213

1314
class BinaryReader
@@ -77,6 +78,11 @@ class BinaryReader
7778
*/
7879
private $int32Reader;
7980

81+
/**
82+
* @var \PhpBinaryReader\Type\Single
83+
*/
84+
private $singleReader;
85+
8086
/**
8187
* @param string|resource $input
8288
* @param int|string $endian
@@ -89,7 +95,7 @@ public function __construct($input, $endian = Endian::ENDIAN_LITTLE)
8995
} else {
9096
$this->setInputHandle($input);
9197
}
92-
98+
9399
$this->eofPosition = fstat($this->getInputHandle())['size'];
94100

95101
$this->setEndian($endian);
@@ -103,6 +109,7 @@ public function __construct($input, $endian = Endian::ENDIAN_LITTLE)
103109
$this->int8Reader = new Int8();
104110
$this->int16Reader = new Int16();
105111
$this->int32Reader = new Int32();
112+
$this->singleReader = new Single();
106113
}
107114

108115
/**
@@ -206,6 +213,14 @@ public function readUInt32()
206213
return $this->int32Reader->read($this);
207214
}
208215

216+
/**
217+
* @return float
218+
*/
219+
public function readSingle()
220+
{
221+
return $this->singleReader->read($this);
222+
}
223+
209224
/**
210225
* @param int $length
211226
* @return string
@@ -420,6 +435,14 @@ public function getInt32Reader()
420435
return $this->int32Reader;
421436
}
422437

438+
/**
439+
* @return \PhpBinaryReader\Type\Single
440+
*/
441+
public function getSingleReader()
442+
{
443+
return $this->singleReader;
444+
}
445+
423446
/**
424447
* @return \PhpBinaryReader\Type\Str
425448
*/

src/Type/Single.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace PhpBinaryReader\Type;
4+
5+
use PhpBinaryReader\BinaryReader;
6+
7+
class Single implements TypeInterface
8+
{
9+
/**
10+
* Returns a 4-bytes floating-point
11+
*
12+
* @param \PhpBinaryReader\BinaryReader $br
13+
* @param null $length
14+
*
15+
* @return float
16+
* @throws \OutOfBoundsException
17+
*/
18+
public function read(BinaryReader &$br, $length = null)
19+
{
20+
if (!$br->canReadBytes(4)) {
21+
throw new \OutOfBoundsException('Cannot read 4-bytes floating-point, it exceeds the boundary of the file');
22+
}
23+
24+
$segment = $br->readFromHandle(4);
25+
26+
if ($br->getCurrentBit() !== 0) {
27+
$data = unpack('N', $segment)[1];
28+
$data = $this->bitReader($br, $data);
29+
30+
$endian = $br->getMachineByteOrder() === $br->getEndian() ? 'N' : 'V';
31+
$segment = pack($endian, $data);
32+
} elseif ($br->getMachineByteOrder() !== $br->getEndian()) {
33+
$segment = pack('N', unpack('V', $segment)[1]);
34+
}
35+
36+
$value = unpack('f', $segment)[1];
37+
38+
return $value;
39+
}
40+
41+
/**
42+
* @param \PhpBinaryReader\BinaryReader $br
43+
* @param int $data
44+
*
45+
* @return int
46+
*/
47+
private function bitReader(BinaryReader $br, $data)
48+
{
49+
$mask = 0x7FFFFFFF >> ($br->getCurrentBit() - 1);
50+
$value = (($data >> (8 - $br->getCurrentBit())) & $mask) | ($br->getNextByte() << (24 + $br->getCurrentBit()));
51+
$br->setNextByte($data & 0xFF);
52+
53+
return $value;
54+
}
55+
}

test/BinaryReaderTest.php

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ public function setUp()
2121
*/
2222
public function testEof($brBig, $brLittle)
2323
{
24-
$brBig->setPosition(15);
24+
$brBig->setPosition(44);
2525
$this->assertFalse($brBig->isEof());
26-
$brBig->setPosition(16);
26+
$brBig->setPosition(45);
2727
$this->assertTrue($brBig->isEof());
2828

29-
$brLittle->setPosition(15);
29+
$brLittle->setPosition(44);
3030
$this->assertFalse($brLittle->isEof());
31-
$brLittle->setPosition(16);
31+
$brLittle->setPosition(45);
3232
$this->assertTrue($brLittle->isEof());
3333
}
3434

@@ -37,12 +37,12 @@ public function testEof($brBig, $brLittle)
3737
*/
3838
public function testCanReadBytes($brBig, $brLittle)
3939
{
40-
$brBig->setPosition(15);
40+
$brBig->setPosition(44);
4141
$this->assertTrue($brBig->canReadBytes());
4242
$this->assertTrue($brBig->canReadBytes(1));
4343
$this->assertFalse($brBig->canReadBytes(2));
4444

45-
$brLittle->setPosition(15);
45+
$brLittle->setPosition(44);
4646
$this->assertTrue($brLittle->canReadBytes());
4747
$this->assertTrue($brLittle->canReadBytes(1));
4848
$this->assertFalse($brLittle->canReadBytes(2));
@@ -114,6 +114,24 @@ public function testInt32($brBig, $brLittle)
114114
$this->assertEquals(3, $brLittle->readUInt32());
115115
}
116116

117+
/**
118+
* @param \PhpBinaryReader\BinaryReader $brBig
119+
* @param \PhpBinaryReader\BinaryReader $brLittle
120+
*
121+
* @dataProvider binaryReaders
122+
*/
123+
public function testSingle(BinaryReader $brBig, BinaryReader $brLittle)
124+
{
125+
$brBig->setPosition(16);
126+
$brLittle->setPosition(16);
127+
128+
$this->assertEquals(1.0, $brBig->readSingle());
129+
$this->assertEquals(1.0, $brLittle->readSingle());
130+
131+
$this->assertEquals(-1.0, $brBig->readSingle());
132+
$this->assertEquals(-1.0, $brLittle->readSingle());
133+
}
134+
117135
/**
118136
* @dataProvider binaryReaders
119137
*/
@@ -207,8 +225,8 @@ public function testPositionSet($brBig, $brLittle)
207225
*/
208226
public function testEofPosition($brBig, $brLittle)
209227
{
210-
$this->assertEquals(16, $brBig->getEofPosition());
211-
$this->assertEquals(16, $brLittle->getEofPosition());
228+
$this->assertEquals(45, $brBig->getEofPosition());
229+
$this->assertEquals(45, $brLittle->getEofPosition());
212230
}
213231

214232
/**
@@ -305,5 +323,6 @@ public function testReaders()
305323
$this->assertInstanceOf('\PhpBinaryReader\Type\Int32', $brBig->getInt32Reader());
306324
$this->assertInstanceOf('\PhpBinaryReader\Type\Int8', $brBig->getInt8Reader());
307325
$this->assertInstanceOf('\PhpBinaryReader\Type\Str', $brBig->getStringReader());
326+
$this->assertInstanceOf('\PhpBinaryReader\Type\Single', $brBig->getSingleReader());
308327
}
309328
}

test/Type/BitTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function testSignedBitReader($brBig, $brLittle)
7777
*/
7878
public function testExceptionBitsBigEndian($brBig, $brLittle)
7979
{
80-
$brBig->setPosition(16);
80+
$brBig->setPosition(45);
8181
$brBig->readBits(16);
8282
}
8383

@@ -87,7 +87,7 @@ public function testExceptionBitsBigEndian($brBig, $brLittle)
8787
*/
8888
public function testExceptionBitsLittleEndian($brBig, $brLittle)
8989
{
90-
$brLittle->setPosition(16);
90+
$brLittle->setPosition(45);
9191
$brLittle->readBits(16);
9292
}
9393

@@ -115,7 +115,7 @@ public function testExceptionInvalidBitCountLittleEndian($brBig, $brLittle)
115115
*/
116116
public function testExceptionBitsOnLastBitsBigEndian($brBig, $brLittle)
117117
{
118-
$brBig->setPosition(15);
118+
$brBig->setPosition(44);
119119
$brBig->readBits(4);
120120
$brBig->readBits(2);
121121
$brBig->readBits(2);
@@ -128,7 +128,7 @@ public function testExceptionBitsOnLastBitsBigEndian($brBig, $brLittle)
128128
*/
129129
public function testExceptionBitsOnLastBitsLittleEndian($brBig, $brLittle)
130130
{
131-
$brLittle->setPosition(15);
131+
$brLittle->setPosition(44);
132132
$brLittle->readBits(4);
133133
$brLittle->readBits(2);
134134
$brLittle->readBits(2);

test/Type/ByteTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function testBytesAreRead($brBig, $brLittle)
3939
*/
4040
public function testExceptionIsThrownIfOutOfBoundsBigEndian($brBig, $brLittle)
4141
{
42-
$brBig->readBits(128);
42+
$brBig->readBits(360);
4343
$this->byte->read($brBig, 1);
4444
}
4545

@@ -49,7 +49,7 @@ public function testExceptionIsThrownIfOutOfBoundsBigEndian($brBig, $brLittle)
4949
*/
5050
public function testExceptionIsThrownIfOutOfBoundsLittleEndian($brBig, $brLittle)
5151
{
52-
$brLittle->readBits(128);
52+
$brLittle->readBits(360);
5353
$this->byte->read($brLittle, 1);
5454
}
5555

test/Type/Int16Test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
102102
*/
103103
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
104104
{
105-
$brBig->readBits(128);
105+
$brBig->readBits(360);
106106
$this->int16->read($brBig);
107107
}
108108

@@ -112,7 +112,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
112112
*/
113113
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
114114
{
115-
$brLittle->readBits(128);
115+
$brLittle->readBits(360);
116116
$this->int16->read($brLittle);
117117
}
118118

test/Type/Int32Test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
8787
*/
8888
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
8989
{
90-
$brBig->readBits(128);
90+
$brBig->readBits(360);
9191
$this->int32->read($brBig);
9292
}
9393

@@ -97,7 +97,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
9797
*/
9898
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
9999
{
100-
$brLittle->readBits(128);
100+
$brLittle->readBits(360);
101101
$this->int32->read($brLittle);
102102
}
103103

test/Type/Int8Test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
117117
*/
118118
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
119119
{
120-
$brBig->readBits(128);
120+
$brBig->readBits(360);
121121
$this->int8->read($brBig);
122122
}
123123

@@ -127,7 +127,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
127127
*/
128128
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
129129
{
130-
$brLittle->readBits(128);
130+
$brLittle->readBits(360);
131131
$this->int8->read($brLittle);
132132
}
133133

0 commit comments

Comments
 (0)