2
namespace GuzzleHttp\Stream;
3
use GuzzleHttp\Stream\Exception\SeekException;
6
* Decorator used to return only a subset of a stream
8
class LimitStream implements StreamInterface, MetadataStreamInterface
10
use StreamDecoratorTrait;
12
/** @var int Offset to start reading from */
15
/** @var int Limit the number of bytes that can be read */
19
* @param StreamInterface $stream Stream to wrap
20
* @param int $limit Total number of bytes to allow to be read
21
* from the stream. Pass -1 for no limit.
22
* @param int|null $offset Position to seek to before reading (only
23
* works on seekable streams).
25
public function __construct(
26
StreamInterface $stream,
30
$this->stream = $stream;
31
$this->setLimit($limit);
32
$this->setOffset($offset);
37
if ($this->limit == -1) {
38
return $this->stream->eof();
41
$tell = $this->stream->tell();
43
return $tell === false ||
44
($tell >= $this->offset + $this->limit) ||
49
* Returns the size of the limited subset of data
52
public function getSize()
54
if (null === ($length = $this->stream->getSize())) {
56
} elseif ($this->limit == -1) {
57
return $length - $this->offset;
59
return min($this->limit, $length - $this->offset);
64
* Allow for a bounded seek on the read limited stream
67
public function seek($offset, $whence = SEEK_SET)
69
if ($whence != SEEK_SET) {
73
if ($offset < $this->offset) {
74
$offset = $this->offset;
77
if ($this->limit !== -1 && $offset > ($this->offset + $this->limit)) {
78
$offset = $this->offset + $this->limit;
81
return $this->stream->seek($offset);
85
* Give a relative tell()
88
public function tell()
90
return $this->stream->tell() - $this->offset;
94
* Set the offset to start limiting from
96
* @param int $offset Offset to seek to and begin byte limiting from
99
* @throws SeekException
101
public function setOffset($offset)
103
$current = $this->stream->tell();
105
if ($current !== $offset) {
106
// If the stream cannot seek to the offset position, then read to it
107
if (!$this->stream->seek($offset)) {
108
if ($current > $offset) {
109
throw new SeekException($this, $offset);
111
$this->stream->read($offset - $current);
116
$this->offset = $offset;
122
* Set the limit of bytes that the decorator allows to be read from the
125
* @param int $limit Number of bytes to allow to be read from the stream.
126
* Use -1 for no limit.
129
public function setLimit($limit)
131
$this->limit = $limit;
136
public function read($length)
138
if ($this->limit == -1) {
139
return $this->stream->read($length);
142
// Check if the current position is less than the total allowed
143
// bytes + original offset
144
$remaining = ($this->offset + $this->limit) - $this->stream->tell();
145
if ($remaining > 0) {
146
// Only return the amount of requested data, ensuring that the byte
147
// limit is not exceeded
148
return $this->stream->read(min($remaining, $length));