From f65c68522992147ad24569c4996e5fdeafde71af Mon Sep 17 00:00:00 2001 From: Valentin <vintsukevich@gmail.com> Date: Tue, 16 Feb 2016 00:23:42 +0300 Subject: [PATCH] INIT --- .gitIgnore | 1 + README.md | 2 +- composer.json | 23 +++ phpunit.xml | 18 +++ src/BinaryGenerator.php | 200 ++++++++++++++++++++++++++ src/Exceptions/GeneratorException.php | 15 ++ src/Exceptions/HandlerException.php | 15 ++ src/Exceptions/ReadDataException.php | 15 ++ src/Exceptions/WriteDataException.php | 15 ++ tests/BinaryTest.php | 32 +++++ tests/assets/.empty | 0 11 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 .gitIgnore create mode 100644 composer.json create mode 100644 phpunit.xml create mode 100644 src/BinaryGenerator.php create mode 100644 src/Exceptions/GeneratorException.php create mode 100644 src/Exceptions/HandlerException.php create mode 100644 src/Exceptions/ReadDataException.php create mode 100644 src/Exceptions/WriteDataException.php create mode 100644 tests/BinaryTest.php create mode 100644 tests/assets/.empty diff --git a/.gitIgnore b/.gitIgnore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitIgnore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 3121a45..fd3d085 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # binary -Lightweight tool to read/write tons of data directly in file, skipping memory usage +Lightweight tool to read/write tons of data directly in file, skipping memory usage \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ececb30 --- /dev/null +++ b/composer.json @@ -0,0 +1,23 @@ +{ + "name": "vvval/binary", + "description": "Lightweight tool to read/write tons of data directly in file, skipping memory usage", + "authors": [ + { + "name": "Valentin V / vvval", + "email": "vintsukevich@gmail.com" + } + ], + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "autoload": { + "psr-4": { + "Vvval\\Binary\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Vvval\\Binary\\Tests\\": "tests" + } + } +} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..94dc2bd --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<phpunit backupGlobals="false" + backupStaticAttributes="false" + colors="true" + verbose="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + stopOnError="false" + syntaxCheck="true"> + <testsuites> + <testsuite name="Application Tests"> + <directory>./tests/</directory> + </testsuite> + </testsuites> +</phpunit> \ No newline at end of file diff --git a/src/BinaryGenerator.php b/src/BinaryGenerator.php new file mode 100644 index 0000000..7d21481 --- /dev/null +++ b/src/BinaryGenerator.php @@ -0,0 +1,200 @@ +<?php +/** + * Lightweight tool to read/write tons of data directly in file, skipping memory usage + * + * @author Valentin V + * @license http://www.opensource.org/licenses/MIT + * @link https://github.com/vvval/binary + * @version 0.1.0 + */ +namespace Vvval\Binary; + +use Vvval\Binary\Exceptions\HandlerException; +use Vvval\Binary\Exceptions\ReadDataException; +use Vvval\Binary\Exceptions\WriteDataException; + +class BinaryGenerator +{ + /** + * todo read about fopen + */ + const READ = 'rb'; + const WRITE = 'wb'; + const APPEND = 'ab'; + + private $filename = null; + private $compression = null; + private $handler = null; + private $mode = self::READ; + + /** + * @param $compression + * @return $this + * @throws HandlerException + */ + public function setCompression($compression) + { + if (!empty($this->handler)) + { + throw new HandlerException("Binary generator has already started with \"$this->filename\" file."); + } + + $this->compression = $compression; + + return $this; + } + + /** + * @param $filename + * @param $mode + * @throws HandlerException + */ + public function start($filename, $mode) + { + $this->mode = $mode; + $this->filename = $filename; + + if (!empty($this->handler)) + { + throw new HandlerException("Binary generator has already started with \"$this->filename\" file."); + } + + if (!empty($this->compression)) + { + $this->handler = gzopen($this->filename, $this->mode); + } + else + { + $this->handler = fopen($this->filename, $this->mode); + } + + if (empty($this->handler)) + { + throw new HandlerException("Error during opening \"$this->filename\" file."); + } + } + + /** + * + */ + public function finish() + { + if (!empty($this->handler)) + { + if (!empty($this->compression)) + { + gzclose($this->handler); + } + else + { + fclose($this->handler); + } + + $this->handler = null; + } + } + + /** + * @param $data + * @return int + * @throws HandlerException + * @throws WriteDataException + */ + public function writeData($data) + { + if (!$this->isWriteMode()) + { + throw new WriteDataException("Unable to write data into \"$this->filename\" file, read mode is set."); + } + + if (empty($this->handler)) + { + throw new HandlerException("Unable to write data into \"$this->filename\" file, no resource is available."); + } + + $packedLength = pack('L', mb_strlen($data)); + + if (!empty($this->compression)) + { + return gzwrite($this->handler, $packedLength . $data); + } + + return fwrite($this->handler, $packedLength . $data); + } + + /** + * @return null|string + * @throws HandlerException + * @throws ReadDataException + */ + public function readData() + { + if (!$this->isReadMode()) + { + throw new ReadDataException("Unable to read data from \"$this->filename\" file, write mode is set."); + } + + if (empty($this->handler)) + { + throw new HandlerException("Unable to read data from \"$this->filename\" file, no resource is available."); + } + + if (!empty($this->compression)) + { + $length = gzread($this->handler, 4); + } + else + { + $length = fread($this->handler, 4); + } + + if (empty($length)) + { + return null; + } + + if (mb_strlen($length) != 4) + { + throw new ReadDataException("Unable to read data from \"$this->filename\" file, data is corrupted."); + } + + $length = unpack('L', $length); + + if (!empty($this->compression)) + { + return gzread($this->handler, $length[1]); + } + else + { + return fread($this->handler, $length[1]); + } + } + + /** + * @return bool + */ + private function isReadMode() + { + return $this->mode === self::READ; + } + + /** + * @return bool + */ + private function isWriteMode() + { + return in_array($this->mode, [self::WRITE, self::APPEND]); + } + + /** + * Check if file was closed. + * + */ + public function __destruct() + { + if (!empty($this->handler)) + { + throw new HandlerException("Binary generator hasn't finished \"$this->filename\" file yet."); + } + } +} \ No newline at end of file diff --git a/src/Exceptions/GeneratorException.php b/src/Exceptions/GeneratorException.php new file mode 100644 index 0000000..eda7391 --- /dev/null +++ b/src/Exceptions/GeneratorException.php @@ -0,0 +1,15 @@ +<?php +/** + * Lightweight tool to read/write tons of data directly in file, skipping memory usage + * + * @author Valentin V + * @license http://www.opensource.org/licenses/MIT + * @link https://github.com/vvval/binary + * @version 0.1.0 + */ +namespace Vvval\Binary\Exceptions; + +class GeneratorException extends \Exception +{ + +} \ No newline at end of file diff --git a/src/Exceptions/HandlerException.php b/src/Exceptions/HandlerException.php new file mode 100644 index 0000000..bc78116 --- /dev/null +++ b/src/Exceptions/HandlerException.php @@ -0,0 +1,15 @@ +<?php +/** + * Lightweight tool to read/write tons of data directly in file, skipping memory usage + * + * @author Valentin V + * @license http://www.opensource.org/licenses/MIT + * @link https://github.com/vvval/binary + * @version 0.1.0 + */ +namespace Vvval\Binary\Exceptions; + +class HandlerException extends GeneratorException +{ + +} \ No newline at end of file diff --git a/src/Exceptions/ReadDataException.php b/src/Exceptions/ReadDataException.php new file mode 100644 index 0000000..a29077d --- /dev/null +++ b/src/Exceptions/ReadDataException.php @@ -0,0 +1,15 @@ +<?php +/** + * Lightweight tool to read/write tons of data directly in file, skipping memory usage + * + * @author Valentin V + * @license http://www.opensource.org/licenses/MIT + * @link https://github.com/vvval/binary + * @version 0.1.0 + */ +namespace Vvval\Binary\Exceptions; + +class ReadDataException extends GeneratorException +{ + +} \ No newline at end of file diff --git a/src/Exceptions/WriteDataException.php b/src/Exceptions/WriteDataException.php new file mode 100644 index 0000000..070eec6 --- /dev/null +++ b/src/Exceptions/WriteDataException.php @@ -0,0 +1,15 @@ +<?php +/** + * Lightweight tool to read/write tons of data directly in file, skipping memory usage + * + * @author Valentin V + * @license http://www.opensource.org/licenses/MIT + * @link https://github.com/vvval/binary + * @version 0.1.0 + */ +namespace Vvval\Binary\Exceptions; + +class WriteDataException extends GeneratorException +{ + +} \ No newline at end of file diff --git a/tests/BinaryTest.php b/tests/BinaryTest.php new file mode 100644 index 0000000..6f01f70 --- /dev/null +++ b/tests/BinaryTest.php @@ -0,0 +1,32 @@ +<?php +/** + * Created by PhpStorm. + * User: Valentin + * Date: 01.02.2016 + * Time: 13:19 + */ + +namespace Vvval\Binary\Tests; + +use Vvval\Binary\BinaryGenerator; + +class BinaryTest extends \PHPUnit_Framework_TestCase +{ + private $writeFile = 'binary.write.txt'; + private $appendFile = 'binary.append.txt'; + + /** + * If data file exists. + */ + public function testBinaryWrite() + { + $binary = new BinaryGenerator(); + + $binary->start($this->writeFile, BinaryGenerator::WRITE); + $binary->writeData('some data.1'); + $binary->writeData('some data.2'); + $binary->finish(); + + $this->assertFileExists($this->writeFile); + } +} \ No newline at end of file diff --git a/tests/assets/.empty b/tests/assets/.empty new file mode 100644 index 0000000..e69de29