From 3675e36c5f2b75e65b8fee13ad38779ba2f99fa7 Mon Sep 17 00:00:00 2001 From: "arjun.kannan" Date: Tue, 12 Mar 2024 16:38:00 +0800 Subject: [PATCH 1/2] Add support for reading double data types A new functionality has been introduced in the BinaryReader class to support reading double data types from binary files. A new 'Double' class has also been created in the Type namespace to handle the actual reading and conversion of the double data types. Accompanying unit tests have been updated to ensure the proper functionality of these new features. --- src/BinaryReader.php | 20 +++++++++++++++ src/Type/Double.php | 53 +++++++++++++++++++++++++++++++++++++++ test/BinaryReaderTest.php | 19 ++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 src/Type/Double.php diff --git a/src/BinaryReader.php b/src/BinaryReader.php index 8e2d4a0..7c7ac54 100644 --- a/src/BinaryReader.php +++ b/src/BinaryReader.php @@ -5,6 +5,7 @@ use PhpBinaryReader\Exception\InvalidDataException; use PhpBinaryReader\Type\Bit; use PhpBinaryReader\Type\Byte; +use PhpBinaryReader\Type\Double; use PhpBinaryReader\Type\Int8; use PhpBinaryReader\Type\Int16; use PhpBinaryReader\Type\Int32; @@ -89,6 +90,11 @@ class BinaryReader */ private $singleReader; + /** + * @var \PhpBinaryReader\Type\Double + */ + private $doubleReader; + /** * @param string|resource $input * @param int|string $endian @@ -117,6 +123,7 @@ public function __construct($input, $endian = Endian::ENDIAN_LITTLE) $this->int32Reader = new Int32(); $this->int64Reader = new Int64(); $this->singleReader = new Single(); + $this->doubleReader = new Double(); } /** @@ -244,6 +251,11 @@ public function readSingle() return $this->singleReader->read($this); } + public function readDouble() + { + return $this->doubleReader->read($this); + } + /** * @param int $length * @return string @@ -474,6 +486,14 @@ public function getSingleReader() return $this->singleReader; } + /** + * @return \PhpBinaryReader\Type\Double + */ + public function getDoubleReader() + { + return $this->doubleReader; + } + /** * @return \PhpBinaryReader\Type\Str */ diff --git a/src/Type/Double.php b/src/Type/Double.php new file mode 100644 index 0000000..7b2f60f --- /dev/null +++ b/src/Type/Double.php @@ -0,0 +1,53 @@ +canReadBytes(8)) { + throw new \OutOfBoundsException('Cannot read 8-bytes double, it exceeds the boundary of the file'); + } + + $segment = $br->readFromHandle(8); + 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 = strrev($segment); + } + + $value = unpack('d', $segment)[1]; + return $value; + } + + /** + * @param \PhpBinaryReader\BinaryReader $br + * @param int $data + * + * @return int + */ + private function bitReader(BinaryReader $br, $data) + { + $mask = 0x7FFFFFFFFFFFFFFF >> ($br->getCurrentBit() - 1); + $value = (($data >> (8 - $br->getCurrentBit())) & $mask) | ($br->getNextByte() << (56 + $br->getCurrentBit())); + $br->setNextByte($data & 0xFF); + return $value; + } +} \ No newline at end of file diff --git a/test/BinaryReaderTest.php b/test/BinaryReaderTest.php index cd02d96..fbcb3e4 100644 --- a/test/BinaryReaderTest.php +++ b/test/BinaryReaderTest.php @@ -147,6 +147,24 @@ public function testSingle(BinaryReader $brBig, BinaryReader $brLittle) $this->assertEquals(-1.0, $brLittle->readSingle()); } + /** + * @param \PhpBinaryReader\BinaryReader $brBig + * @param \PhpBinaryReader\BinaryReader $brLittle + * + * @dataProvider binaryReaders + */ + public function testDouble(BinaryReader $brBig, BinaryReader $brLittle) + { + $brBig->setPosition(16); + $brLittle->setPosition(16); + + $this->assertEquals(1.0, $brBig->readDouble()); + $this->assertEquals(1.0, $brLittle->readDouble()); + + $this->assertEquals(-1.0, $brBig->readDouble()); + $this->assertEquals(-1.0, $brLittle->readDouble()); + } + /** * @dataProvider binaryReaders */ @@ -340,5 +358,6 @@ public function testReaders() $this->assertInstanceOf('\PhpBinaryReader\Type\Int8', $brBig->getInt8Reader()); $this->assertInstanceOf('\PhpBinaryReader\Type\Str', $brBig->getStringReader()); $this->assertInstanceOf('\PhpBinaryReader\Type\Single', $brBig->getSingleReader()); + $this->assertInstanceOf('\PhpBinaryReader\Type\Double', $brBig->getDoubleReader()); } } From 91ac31a6e2e3be74f08cd2091f5324b9fe3868bc Mon Sep 17 00:00:00 2001 From: "arjun.kannan" Date: Tue, 12 Mar 2024 16:40:19 +0800 Subject: [PATCH 2/2] Add readDouble() function description to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index dfae616..ac8318c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ Methods **readSingle()** returns a 4-bytes floating-point +**readDouble()** returns a 8-bytes signed double + **readUBits($length)** returns a variable length of bits (unsigned) **readBits($length)** returns a variable length of bits (signed)