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