Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
rkrx committed Feb 9, 2014
1 parent aa9ebce commit f520a7d
Show file tree
Hide file tree
Showing 8 changed files with 675 additions and 29 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Method | Return-type | Possible exception(s)

### InfiniteInputStream

An `InfiniteInputStream` is a read-only stream that has no end. The `InputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then reading data. It does not ship methods to open or close a stream.
An `InfiniteInputStream` is a read-only stream that has no end. The `InputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then reading data.

Examples:

Expand All @@ -91,7 +91,7 @@ Examples:

### InputStream

An `InputStream` is a read-only stream that has an end. The `InputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then reading data and closing the stream.
An `InputStream` is a read-only stream that has an end. The `InputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then reading data.

The `InputStream` publish these methods:

Expand All @@ -113,11 +113,14 @@ Examples:

### OutputStream

An `OutputStream` is a write-only stream. It has no information on its size or the cursor-position in the stream. The `OutputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then writing data and closing the stream.
An `OutputStream` is a write-only stream. It has no information on its size or the cursor-position in the stream. The `OutputStream` is good for situations were it doesn't matter if a `Stream` has other abilities then writing data.

Method | Return-type | Possible exception(s)
------ | ----------- | ---------------------
`write($data)` | `static` | IOException
`flush()` | `static` | IOException



Examples:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php
namespace Kir\Streams\Exceptions;

class InvalidStreamOperationException extends IOException {
}
6 changes: 6 additions & 0 deletions src/Kir/Streams/OutputStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ interface OutputStream extends Stream {
* @return $this
*/
public function write($data);

/**
* @throws IOException
* @return $this
*/
public function flush();
}
10 changes: 10 additions & 0 deletions tests/Kir/Streams/Helper/MemoryStream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
namespace Kir\Streams\Helper;

class MemoryStream extends ResourceStream {
/**
*/
public function __construct() {
parent::__construct('php://memory', 'r+');
}
}
92 changes: 92 additions & 0 deletions tests/Kir/Streams/Helper/NondestructiveReadWriteStream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
namespace Kir\Streams\Helper;

use Kir\Streams\Exceptions\IOException;
use Kir\Streams\RandomAccessStream;

class NondestructiveReadWriteStream implements RandomAccessStream {
/**
* @var RandomAccessStream
*/
private $stream = null;

/**
* @param RandomAccessStream $sourceStream
*/
public function __construct(RandomAccessStream $sourceStream) {
// Should solved differently some time
$this->stream = new MemoryStream();
$this->stream->write($sourceStream->read());
$this->stream->rewind();
}

/**
* @throws IOException
* @param int $length
* @return string
*/
public function read($length = null) {
return $this->stream->read($length);
}

/**
* @return bool
*/
public function isAtEnd() {
return $this->stream->isAtEnd();
}

/**
* @throws IOException
* @param string $data
* @return $this
*/
public function write($data) {
$this->stream->write($data);
return $this;
}

/**
* @throws IOException
* @return $this
*/
public function flush() {
$this->stream->flush();
return $this;
}

/**
* @throws IOException
* @param int $pos
* @return $this
*/
public function setPosition($pos) {
$this->stream->setPosition($pos);
return $this;
}

/**
* @throws IOException
* @return int
*/
public function getPosition() {
return $this->stream->getPosition();
}

/**
* @throws IOException
* @return $this
*/
public function rewind() {
$this->stream->rewind();
return $this;
}

/**
* @throws IOException
* @return int
*/
public function getSize() {
return $this->stream->getSize();
}
}
189 changes: 189 additions & 0 deletions tests/Kir/Streams/Helper/ResourceStream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php
namespace Kir\Streams\Helper;

use Kir\Streams\Exceptions\InvalidStreamOperationException;
use Kir\Streams\Exceptions\IOException;
use Kir\Streams\RandomAccessStream;

class ResourceStream implements RandomAccessStream {
/**
* @var resource
*/
private $res = null;

/**
* @var int
*/
private $size = null;

/**
* @var array
*/
private $meta = array();

/**
* @param string $filename
* @param string $mode
*/
public function __construct($filename, $mode) {
$this->res = fopen($filename, $mode);
}

/**
*/
public function __destruct() {
try {
$this->disconnect();
} catch (\Exception $e) {
}
}

/**
* @throws IOException
* @return $this
*/
public function disconnect() {
try {
if($this->res === null) {
return;
}
if(!@fclose($this->res)) {
throw new IOException("Could not close stream");
}
} catch (IOException $e) {
throw $e;
} catch (\Exception $e) {
new IOException($e->getMessage(), $e->getCode(), $e);
}
}

/**
* @return bool
*/
public function isAtEnd() {
return feof($this->res);
}

/**
* @param int $length
* @return string
*/
public function read($length = null) {
if($length === null) {
$length = -1;
}
$data = stream_get_contents($this->res, $length);
return $data;
}

/**
* @param string $data
* @return $this
*/
public function write($data) {
fwrite($this->res, $data);
$this->size = max(ftell($this->res), $this->size);
return $this;
}
/**
* @throws IOException
* @return $this
*/
public function flush() {
return $this;
}

/**
* @return int
*/
public function getPosition() {
if($this->isSeekable()) {
return ftell($this->res);
}
return null;
}

/**
* @param int $pos
* @throws InvalidStreamOperationException
* @return $this
*/
public function setPosition($pos) {
if (!$this->isSeekable()) {
throw new InvalidStreamOperationException("Stream is not seekable");
}

$pos = min($pos, $this->getSize() - 1);
$pos = max($pos, 0);

fseek($this->res, $pos, SEEK_SET);

if(ftell($this->res) == $pos) {
return $this;
}

rewind($this->res);
fread($this->res, $pos);

if(ftell($this->res) != $pos) {
throw new InvalidStreamOperationException("Unable to set position");
}

return $this;
}

/**
* @return $this
*/
public function rewind() {
rewind($this->res);
return $this;
}

/**
* @return int
*/
public function getSize() {
$this->updateSize();
return $this->size;
}

/**
* @param int $size
* @return $this
*/
public function truncate($size = 0) {
ftruncate($this->res, $size);
$this->rewind();
return $this;
}

/**
* @return bool
*/
protected function isSeekable() {
return !!$this->getMetaValue('seekable');
}

/**
* @param resource $resource
*/
protected function setResource($resource) {
$this->res = $resource;
$this->meta = stream_get_meta_data($this->res);
$this->meta = is_array($this->meta) ? $this->meta : array();

if ($this->isSeekable()) {
$pos = ftell($this->res);
fseek($this->res, 0, SEEK_END);
$this->size = ftell($this->res);
fseek($this->res, $pos, SEEK_SET);
}
}

/**
*/
private function updateSize() {
$this->size = max(ftell($this->res), $this->size);
}
}
Loading

0 comments on commit f520a7d

Please sign in to comment.