Skip to content

Commit

Permalink
Merge pull request #12 from nsknewbie/feature/float-reader
Browse files Browse the repository at this point in the history
implemented 4-bytes floating-point reader
  • Loading branch information
mdurrant committed Jun 14, 2016
2 parents 55c1c2e + 4c014e0 commit 23e08d5
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 23 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Methods

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

**readSingle()** returns a 4-bytes floating-point

**readUBits($length)** returns a variable length of bits (unsigned)

**readBits($length)** returns a variable length of bits (signed)
Expand Down
25 changes: 24 additions & 1 deletion src/BinaryReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpBinaryReader\Type\Int8;
use PhpBinaryReader\Type\Int16;
use PhpBinaryReader\Type\Int32;
use PhpBinaryReader\Type\Single;
use PhpBinaryReader\Type\Str;

class BinaryReader
Expand Down Expand Up @@ -77,6 +78,11 @@ class BinaryReader
*/
private $int32Reader;

/**
* @var \PhpBinaryReader\Type\Single
*/
private $singleReader;

/**
* @param string|resource $input
* @param int|string $endian
Expand All @@ -89,7 +95,7 @@ public function __construct($input, $endian = Endian::ENDIAN_LITTLE)
} else {
$this->setInputHandle($input);
}

$this->eofPosition = fstat($this->getInputHandle())['size'];

$this->setEndian($endian);
Expand All @@ -103,6 +109,7 @@ public function __construct($input, $endian = Endian::ENDIAN_LITTLE)
$this->int8Reader = new Int8();
$this->int16Reader = new Int16();
$this->int32Reader = new Int32();
$this->singleReader = new Single();
}

/**
Expand Down Expand Up @@ -206,6 +213,14 @@ public function readUInt32()
return $this->int32Reader->read($this);
}

/**
* @return float
*/
public function readSingle()
{
return $this->singleReader->read($this);
}

/**
* @param int $length
* @return string
Expand Down Expand Up @@ -420,6 +435,14 @@ public function getInt32Reader()
return $this->int32Reader;
}

/**
* @return \PhpBinaryReader\Type\Single
*/
public function getSingleReader()
{
return $this->singleReader;
}

/**
* @return \PhpBinaryReader\Type\Str
*/
Expand Down
55 changes: 55 additions & 0 deletions src/Type/Single.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace PhpBinaryReader\Type;

use PhpBinaryReader\BinaryReader;

class Single implements TypeInterface
{
/**
* Returns a 4-bytes floating-point
*
* @param \PhpBinaryReader\BinaryReader $br
* @param null $length
*
* @return float
* @throws \OutOfBoundsException
*/
public function read(BinaryReader &$br, $length = null)
{
if (!$br->canReadBytes(4)) {
throw new \OutOfBoundsException('Cannot read 4-bytes floating-point, it exceeds the boundary of the file');
}

$segment = $br->readFromHandle(4);

if ($br->getCurrentBit() !== 0) {
$data = unpack('N', $segment)[1];
$data = $this->bitReader($br, $data);

$endian = $br->getMachineByteOrder() === $br->getEndian() ? 'N' : 'V';
$segment = pack($endian, $data);
} elseif ($br->getMachineByteOrder() !== $br->getEndian()) {
$segment = pack('N', unpack('V', $segment)[1]);
}

$value = unpack('f', $segment)[1];

return $value;
}

/**
* @param \PhpBinaryReader\BinaryReader $br
* @param int $data
*
* @return int
*/
private function bitReader(BinaryReader $br, $data)
{
$mask = 0x7FFFFFFF >> ($br->getCurrentBit() - 1);
$value = (($data >> (8 - $br->getCurrentBit())) & $mask) | ($br->getNextByte() << (24 + $br->getCurrentBit()));
$br->setNextByte($data & 0xFF);

return $value;
}
}
35 changes: 27 additions & 8 deletions test/BinaryReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public function setUp()
*/
public function testEof($brBig, $brLittle)
{
$brBig->setPosition(15);
$brBig->setPosition(44);
$this->assertFalse($brBig->isEof());
$brBig->setPosition(16);
$brBig->setPosition(45);
$this->assertTrue($brBig->isEof());

$brLittle->setPosition(15);
$brLittle->setPosition(44);
$this->assertFalse($brLittle->isEof());
$brLittle->setPosition(16);
$brLittle->setPosition(45);
$this->assertTrue($brLittle->isEof());
}

Expand All @@ -37,12 +37,12 @@ public function testEof($brBig, $brLittle)
*/
public function testCanReadBytes($brBig, $brLittle)
{
$brBig->setPosition(15);
$brBig->setPosition(44);
$this->assertTrue($brBig->canReadBytes());
$this->assertTrue($brBig->canReadBytes(1));
$this->assertFalse($brBig->canReadBytes(2));

$brLittle->setPosition(15);
$brLittle->setPosition(44);
$this->assertTrue($brLittle->canReadBytes());
$this->assertTrue($brLittle->canReadBytes(1));
$this->assertFalse($brLittle->canReadBytes(2));
Expand Down Expand Up @@ -114,6 +114,24 @@ public function testInt32($brBig, $brLittle)
$this->assertEquals(3, $brLittle->readUInt32());
}

/**
* @param \PhpBinaryReader\BinaryReader $brBig
* @param \PhpBinaryReader\BinaryReader $brLittle
*
* @dataProvider binaryReaders
*/
public function testSingle(BinaryReader $brBig, BinaryReader $brLittle)
{
$brBig->setPosition(16);
$brLittle->setPosition(16);

$this->assertEquals(1.0, $brBig->readSingle());
$this->assertEquals(1.0, $brLittle->readSingle());

$this->assertEquals(-1.0, $brBig->readSingle());
$this->assertEquals(-1.0, $brLittle->readSingle());
}

/**
* @dataProvider binaryReaders
*/
Expand Down Expand Up @@ -207,8 +225,8 @@ public function testPositionSet($brBig, $brLittle)
*/
public function testEofPosition($brBig, $brLittle)
{
$this->assertEquals(16, $brBig->getEofPosition());
$this->assertEquals(16, $brLittle->getEofPosition());
$this->assertEquals(45, $brBig->getEofPosition());
$this->assertEquals(45, $brLittle->getEofPosition());
}

/**
Expand Down Expand Up @@ -305,5 +323,6 @@ public function testReaders()
$this->assertInstanceOf('\PhpBinaryReader\Type\Int32', $brBig->getInt32Reader());
$this->assertInstanceOf('\PhpBinaryReader\Type\Int8', $brBig->getInt8Reader());
$this->assertInstanceOf('\PhpBinaryReader\Type\Str', $brBig->getStringReader());
$this->assertInstanceOf('\PhpBinaryReader\Type\Single', $brBig->getSingleReader());
}
}
8 changes: 4 additions & 4 deletions test/Type/BitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function testSignedBitReader($brBig, $brLittle)
*/
public function testExceptionBitsBigEndian($brBig, $brLittle)
{
$brBig->setPosition(16);
$brBig->setPosition(45);
$brBig->readBits(16);
}

Expand All @@ -87,7 +87,7 @@ public function testExceptionBitsBigEndian($brBig, $brLittle)
*/
public function testExceptionBitsLittleEndian($brBig, $brLittle)
{
$brLittle->setPosition(16);
$brLittle->setPosition(45);
$brLittle->readBits(16);
}

Expand Down Expand Up @@ -115,7 +115,7 @@ public function testExceptionInvalidBitCountLittleEndian($brBig, $brLittle)
*/
public function testExceptionBitsOnLastBitsBigEndian($brBig, $brLittle)
{
$brBig->setPosition(15);
$brBig->setPosition(44);
$brBig->readBits(4);
$brBig->readBits(2);
$brBig->readBits(2);
Expand All @@ -128,7 +128,7 @@ public function testExceptionBitsOnLastBitsBigEndian($brBig, $brLittle)
*/
public function testExceptionBitsOnLastBitsLittleEndian($brBig, $brLittle)
{
$brLittle->setPosition(15);
$brLittle->setPosition(44);
$brLittle->readBits(4);
$brLittle->readBits(2);
$brLittle->readBits(2);
Expand Down
4 changes: 2 additions & 2 deletions test/Type/ByteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function testBytesAreRead($brBig, $brLittle)
*/
public function testExceptionIsThrownIfOutOfBoundsBigEndian($brBig, $brLittle)
{
$brBig->readBits(128);
$brBig->readBits(360);
$this->byte->read($brBig, 1);
}

Expand All @@ -49,7 +49,7 @@ public function testExceptionIsThrownIfOutOfBoundsBigEndian($brBig, $brLittle)
*/
public function testExceptionIsThrownIfOutOfBoundsLittleEndian($brBig, $brLittle)
{
$brLittle->readBits(128);
$brLittle->readBits(360);
$this->byte->read($brLittle, 1);
}

Expand Down
4 changes: 2 additions & 2 deletions test/Type/Int16Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
{
$brBig->readBits(128);
$brBig->readBits(360);
$this->int16->read($brBig);
}

Expand All @@ -112,7 +112,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
{
$brLittle->readBits(128);
$brLittle->readBits(360);
$this->int16->read($brLittle);
}

Expand Down
4 changes: 2 additions & 2 deletions test/Type/Int32Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
{
$brBig->readBits(128);
$brBig->readBits(360);
$this->int32->read($brBig);
}

Expand All @@ -97,7 +97,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
{
$brLittle->readBits(128);
$brLittle->readBits(360);
$this->int32->read($brLittle);
}

Expand Down
4 changes: 2 additions & 2 deletions test/Type/Int8Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public function testBitReaderWithLittleEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
{
$brBig->readBits(128);
$brBig->readBits(360);
$this->int8->read($brBig);
}

Expand All @@ -127,7 +127,7 @@ public function testOutOfBoundsExceptionIsThrownWithBigEndian($brBig, $brLittle)
*/
public function testOutOfBoundsExceptionIsThrownWithLittleEndian($brBig, $brLittle)
{
$brLittle->readBits(128);
$brLittle->readBits(360);
$this->int8->read($brLittle);
}

Expand Down

0 comments on commit 23e08d5

Please sign in to comment.