Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@12
|
3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
|
Chris@12
|
4 * @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
|
Chris@0
|
5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 namespace Zend\Diactoros;
|
Chris@0
|
9
|
Chris@0
|
10 use Psr\Http\Message\StreamInterface;
|
Chris@0
|
11 use RuntimeException;
|
Chris@0
|
12
|
Chris@16
|
13 use const SEEK_SET;
|
Chris@16
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Class RelativeStream
|
Chris@0
|
17 *
|
Chris@0
|
18 * Wrapper for default Stream class, representing subpart (starting from given offset) of initial stream.
|
Chris@0
|
19 * It can be used to avoid copying full stream, conserving memory.
|
Chris@0
|
20 * @example see Zend\Diactoros\AbstractSerializer::splitStream()
|
Chris@0
|
21 */
|
Chris@0
|
22 final class RelativeStream implements StreamInterface
|
Chris@0
|
23 {
|
Chris@0
|
24 /**
|
Chris@0
|
25 * @var StreamInterface
|
Chris@0
|
26 */
|
Chris@0
|
27 private $decoratedStream;
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * @var int
|
Chris@0
|
31 */
|
Chris@0
|
32 private $offset;
|
Chris@0
|
33
|
Chris@0
|
34 /**
|
Chris@0
|
35 * Class constructor
|
Chris@0
|
36 *
|
Chris@0
|
37 * @param StreamInterface $decoratedStream
|
Chris@0
|
38 * @param int $offset
|
Chris@0
|
39 */
|
Chris@0
|
40 public function __construct(StreamInterface $decoratedStream, $offset)
|
Chris@0
|
41 {
|
Chris@0
|
42 $this->decoratedStream = $decoratedStream;
|
Chris@0
|
43 $this->offset = (int)$offset;
|
Chris@0
|
44 }
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * {@inheritdoc}
|
Chris@0
|
48 */
|
Chris@0
|
49 public function __toString()
|
Chris@0
|
50 {
|
Chris@0
|
51 if ($this->isSeekable()) {
|
Chris@0
|
52 $this->seek(0);
|
Chris@0
|
53 }
|
Chris@0
|
54 return $this->getContents();
|
Chris@0
|
55 }
|
Chris@0
|
56
|
Chris@0
|
57 /**
|
Chris@0
|
58 * {@inheritdoc}
|
Chris@0
|
59 */
|
Chris@0
|
60 public function close()
|
Chris@0
|
61 {
|
Chris@0
|
62 $this->decoratedStream->close();
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 /**
|
Chris@0
|
66 * {@inheritdoc}
|
Chris@0
|
67 */
|
Chris@0
|
68 public function detach()
|
Chris@0
|
69 {
|
Chris@0
|
70 return $this->decoratedStream->detach();
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 /**
|
Chris@0
|
74 * {@inheritdoc}
|
Chris@0
|
75 */
|
Chris@0
|
76 public function getSize()
|
Chris@0
|
77 {
|
Chris@0
|
78 return $this->decoratedStream->getSize() - $this->offset;
|
Chris@0
|
79 }
|
Chris@0
|
80
|
Chris@0
|
81 /**
|
Chris@0
|
82 * {@inheritdoc}
|
Chris@0
|
83 */
|
Chris@0
|
84 public function tell()
|
Chris@0
|
85 {
|
Chris@0
|
86 return $this->decoratedStream->tell() - $this->offset;
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 /**
|
Chris@0
|
90 * {@inheritdoc}
|
Chris@0
|
91 */
|
Chris@0
|
92 public function eof()
|
Chris@0
|
93 {
|
Chris@0
|
94 return $this->decoratedStream->eof();
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97 /**
|
Chris@0
|
98 * {@inheritdoc}
|
Chris@0
|
99 */
|
Chris@0
|
100 public function isSeekable()
|
Chris@0
|
101 {
|
Chris@0
|
102 return $this->decoratedStream->isSeekable();
|
Chris@0
|
103 }
|
Chris@0
|
104
|
Chris@0
|
105 /**
|
Chris@0
|
106 * {@inheritdoc}
|
Chris@0
|
107 */
|
Chris@0
|
108 public function seek($offset, $whence = SEEK_SET)
|
Chris@0
|
109 {
|
Chris@0
|
110 if ($whence == SEEK_SET) {
|
Chris@0
|
111 return $this->decoratedStream->seek($offset + $this->offset, $whence);
|
Chris@0
|
112 }
|
Chris@0
|
113 return $this->decoratedStream->seek($offset, $whence);
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 /**
|
Chris@0
|
117 * {@inheritdoc}
|
Chris@0
|
118 */
|
Chris@0
|
119 public function rewind()
|
Chris@0
|
120 {
|
Chris@0
|
121 return $this->seek(0);
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 /**
|
Chris@0
|
125 * {@inheritdoc}
|
Chris@0
|
126 */
|
Chris@0
|
127 public function isWritable()
|
Chris@0
|
128 {
|
Chris@0
|
129 return $this->decoratedStream->isWritable();
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@0
|
132 /**
|
Chris@0
|
133 * {@inheritdoc}
|
Chris@0
|
134 */
|
Chris@0
|
135 public function write($string)
|
Chris@0
|
136 {
|
Chris@0
|
137 if ($this->tell() < 0) {
|
Chris@0
|
138 throw new RuntimeException('Invalid pointer position');
|
Chris@0
|
139 }
|
Chris@0
|
140 return $this->decoratedStream->write($string);
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 /**
|
Chris@0
|
144 * {@inheritdoc}
|
Chris@0
|
145 */
|
Chris@0
|
146 public function isReadable()
|
Chris@0
|
147 {
|
Chris@0
|
148 return $this->decoratedStream->isReadable();
|
Chris@0
|
149 }
|
Chris@0
|
150
|
Chris@0
|
151 /**
|
Chris@0
|
152 * {@inheritdoc}
|
Chris@0
|
153 */
|
Chris@0
|
154 public function read($length)
|
Chris@0
|
155 {
|
Chris@0
|
156 if ($this->tell() < 0) {
|
Chris@0
|
157 throw new RuntimeException('Invalid pointer position');
|
Chris@0
|
158 }
|
Chris@0
|
159 return $this->decoratedStream->read($length);
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 /**
|
Chris@0
|
163 * {@inheritdoc}
|
Chris@0
|
164 */
|
Chris@0
|
165 public function getContents()
|
Chris@0
|
166 {
|
Chris@0
|
167 if ($this->tell() < 0) {
|
Chris@0
|
168 throw new RuntimeException('Invalid pointer position');
|
Chris@0
|
169 }
|
Chris@0
|
170 return $this->decoratedStream->getContents();
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 /**
|
Chris@0
|
174 * {@inheritdoc}
|
Chris@0
|
175 */
|
Chris@0
|
176 public function getMetadata($key = null)
|
Chris@0
|
177 {
|
Chris@0
|
178 return $this->decoratedStream->getMetadata($key);
|
Chris@0
|
179 }
|
Chris@0
|
180 }
|