annotate vendor/guzzlehttp/psr7/src/LimitStream.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2 namespace GuzzleHttp\Psr7;
Chris@0 3
Chris@0 4 use Psr\Http\Message\StreamInterface;
Chris@0 5
Chris@0 6
Chris@0 7 /**
Chris@0 8 * Decorator used to return only a subset of a stream
Chris@0 9 */
Chris@0 10 class LimitStream implements StreamInterface
Chris@0 11 {
Chris@0 12 use StreamDecoratorTrait;
Chris@0 13
Chris@0 14 /** @var int Offset to start reading from */
Chris@0 15 private $offset;
Chris@0 16
Chris@0 17 /** @var int Limit the number of bytes that can be read */
Chris@0 18 private $limit;
Chris@0 19
Chris@0 20 /**
Chris@0 21 * @param StreamInterface $stream Stream to wrap
Chris@0 22 * @param int $limit Total number of bytes to allow to be read
Chris@0 23 * from the stream. Pass -1 for no limit.
Chris@0 24 * @param int $offset Position to seek to before reading (only
Chris@0 25 * works on seekable streams).
Chris@0 26 */
Chris@0 27 public function __construct(
Chris@0 28 StreamInterface $stream,
Chris@0 29 $limit = -1,
Chris@0 30 $offset = 0
Chris@0 31 ) {
Chris@0 32 $this->stream = $stream;
Chris@0 33 $this->setLimit($limit);
Chris@0 34 $this->setOffset($offset);
Chris@0 35 }
Chris@0 36
Chris@0 37 public function eof()
Chris@0 38 {
Chris@0 39 // Always return true if the underlying stream is EOF
Chris@0 40 if ($this->stream->eof()) {
Chris@0 41 return true;
Chris@0 42 }
Chris@0 43
Chris@0 44 // No limit and the underlying stream is not at EOF
Chris@0 45 if ($this->limit == -1) {
Chris@0 46 return false;
Chris@0 47 }
Chris@0 48
Chris@0 49 return $this->stream->tell() >= $this->offset + $this->limit;
Chris@0 50 }
Chris@0 51
Chris@0 52 /**
Chris@0 53 * Returns the size of the limited subset of data
Chris@0 54 * {@inheritdoc}
Chris@0 55 */
Chris@0 56 public function getSize()
Chris@0 57 {
Chris@0 58 if (null === ($length = $this->stream->getSize())) {
Chris@0 59 return null;
Chris@0 60 } elseif ($this->limit == -1) {
Chris@0 61 return $length - $this->offset;
Chris@0 62 } else {
Chris@0 63 return min($this->limit, $length - $this->offset);
Chris@0 64 }
Chris@0 65 }
Chris@0 66
Chris@0 67 /**
Chris@0 68 * Allow for a bounded seek on the read limited stream
Chris@0 69 * {@inheritdoc}
Chris@0 70 */
Chris@0 71 public function seek($offset, $whence = SEEK_SET)
Chris@0 72 {
Chris@0 73 if ($whence !== SEEK_SET || $offset < 0) {
Chris@0 74 throw new \RuntimeException(sprintf(
Chris@0 75 'Cannot seek to offset % with whence %s',
Chris@0 76 $offset,
Chris@0 77 $whence
Chris@0 78 ));
Chris@0 79 }
Chris@0 80
Chris@0 81 $offset += $this->offset;
Chris@0 82
Chris@0 83 if ($this->limit !== -1) {
Chris@0 84 if ($offset > $this->offset + $this->limit) {
Chris@0 85 $offset = $this->offset + $this->limit;
Chris@0 86 }
Chris@0 87 }
Chris@0 88
Chris@0 89 $this->stream->seek($offset);
Chris@0 90 }
Chris@0 91
Chris@0 92 /**
Chris@0 93 * Give a relative tell()
Chris@0 94 * {@inheritdoc}
Chris@0 95 */
Chris@0 96 public function tell()
Chris@0 97 {
Chris@0 98 return $this->stream->tell() - $this->offset;
Chris@0 99 }
Chris@0 100
Chris@0 101 /**
Chris@0 102 * Set the offset to start limiting from
Chris@0 103 *
Chris@0 104 * @param int $offset Offset to seek to and begin byte limiting from
Chris@0 105 *
Chris@0 106 * @throws \RuntimeException if the stream cannot be seeked.
Chris@0 107 */
Chris@0 108 public function setOffset($offset)
Chris@0 109 {
Chris@0 110 $current = $this->stream->tell();
Chris@0 111
Chris@0 112 if ($current !== $offset) {
Chris@0 113 // If the stream cannot seek to the offset position, then read to it
Chris@0 114 if ($this->stream->isSeekable()) {
Chris@0 115 $this->stream->seek($offset);
Chris@0 116 } elseif ($current > $offset) {
Chris@0 117 throw new \RuntimeException("Could not seek to stream offset $offset");
Chris@0 118 } else {
Chris@0 119 $this->stream->read($offset - $current);
Chris@0 120 }
Chris@0 121 }
Chris@0 122
Chris@0 123 $this->offset = $offset;
Chris@0 124 }
Chris@0 125
Chris@0 126 /**
Chris@0 127 * Set the limit of bytes that the decorator allows to be read from the
Chris@0 128 * stream.
Chris@0 129 *
Chris@0 130 * @param int $limit Number of bytes to allow to be read from the stream.
Chris@0 131 * Use -1 for no limit.
Chris@0 132 */
Chris@0 133 public function setLimit($limit)
Chris@0 134 {
Chris@0 135 $this->limit = $limit;
Chris@0 136 }
Chris@0 137
Chris@0 138 public function read($length)
Chris@0 139 {
Chris@0 140 if ($this->limit == -1) {
Chris@0 141 return $this->stream->read($length);
Chris@0 142 }
Chris@0 143
Chris@0 144 // Check if the current position is less than the total allowed
Chris@0 145 // bytes + original offset
Chris@0 146 $remaining = ($this->offset + $this->limit) - $this->stream->tell();
Chris@0 147 if ($remaining > 0) {
Chris@0 148 // Only return the amount of requested data, ensuring that the byte
Chris@0 149 // limit is not exceeded
Chris@0 150 return $this->stream->read(min($remaining, $length));
Chris@0 151 }
Chris@0 152
Chris@0 153 return '';
Chris@0 154 }
Chris@0 155 }