Mercurial > hg > isophonics-drupal-site
comparison vendor/guzzlehttp/psr7/src/AppendStream.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 namespace GuzzleHttp\Psr7; | |
3 | |
4 use Psr\Http\Message\StreamInterface; | |
5 | |
6 /** | |
7 * Reads from multiple streams, one after the other. | |
8 * | |
9 * This is a read-only stream decorator. | |
10 */ | |
11 class AppendStream implements StreamInterface | |
12 { | |
13 /** @var StreamInterface[] Streams being decorated */ | |
14 private $streams = []; | |
15 | |
16 private $seekable = true; | |
17 private $current = 0; | |
18 private $pos = 0; | |
19 private $detached = false; | |
20 | |
21 /** | |
22 * @param StreamInterface[] $streams Streams to decorate. Each stream must | |
23 * be readable. | |
24 */ | |
25 public function __construct(array $streams = []) | |
26 { | |
27 foreach ($streams as $stream) { | |
28 $this->addStream($stream); | |
29 } | |
30 } | |
31 | |
32 public function __toString() | |
33 { | |
34 try { | |
35 $this->rewind(); | |
36 return $this->getContents(); | |
37 } catch (\Exception $e) { | |
38 return ''; | |
39 } | |
40 } | |
41 | |
42 /** | |
43 * Add a stream to the AppendStream | |
44 * | |
45 * @param StreamInterface $stream Stream to append. Must be readable. | |
46 * | |
47 * @throws \InvalidArgumentException if the stream is not readable | |
48 */ | |
49 public function addStream(StreamInterface $stream) | |
50 { | |
51 if (!$stream->isReadable()) { | |
52 throw new \InvalidArgumentException('Each stream must be readable'); | |
53 } | |
54 | |
55 // The stream is only seekable if all streams are seekable | |
56 if (!$stream->isSeekable()) { | |
57 $this->seekable = false; | |
58 } | |
59 | |
60 $this->streams[] = $stream; | |
61 } | |
62 | |
63 public function getContents() | |
64 { | |
65 return copy_to_string($this); | |
66 } | |
67 | |
68 /** | |
69 * Closes each attached stream. | |
70 * | |
71 * {@inheritdoc} | |
72 */ | |
73 public function close() | |
74 { | |
75 $this->pos = $this->current = 0; | |
76 | |
77 foreach ($this->streams as $stream) { | |
78 $stream->close(); | |
79 } | |
80 | |
81 $this->streams = []; | |
82 } | |
83 | |
84 /** | |
85 * Detaches each attached stream | |
86 * | |
87 * {@inheritdoc} | |
88 */ | |
89 public function detach() | |
90 { | |
91 $this->close(); | |
92 $this->detached = true; | |
93 } | |
94 | |
95 public function tell() | |
96 { | |
97 return $this->pos; | |
98 } | |
99 | |
100 /** | |
101 * Tries to calculate the size by adding the size of each stream. | |
102 * | |
103 * If any of the streams do not return a valid number, then the size of the | |
104 * append stream cannot be determined and null is returned. | |
105 * | |
106 * {@inheritdoc} | |
107 */ | |
108 public function getSize() | |
109 { | |
110 $size = 0; | |
111 | |
112 foreach ($this->streams as $stream) { | |
113 $s = $stream->getSize(); | |
114 if ($s === null) { | |
115 return null; | |
116 } | |
117 $size += $s; | |
118 } | |
119 | |
120 return $size; | |
121 } | |
122 | |
123 public function eof() | |
124 { | |
125 return !$this->streams || | |
126 ($this->current >= count($this->streams) - 1 && | |
127 $this->streams[$this->current]->eof()); | |
128 } | |
129 | |
130 public function rewind() | |
131 { | |
132 $this->seek(0); | |
133 } | |
134 | |
135 /** | |
136 * Attempts to seek to the given position. Only supports SEEK_SET. | |
137 * | |
138 * {@inheritdoc} | |
139 */ | |
140 public function seek($offset, $whence = SEEK_SET) | |
141 { | |
142 if (!$this->seekable) { | |
143 throw new \RuntimeException('This AppendStream is not seekable'); | |
144 } elseif ($whence !== SEEK_SET) { | |
145 throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); | |
146 } | |
147 | |
148 $this->pos = $this->current = 0; | |
149 | |
150 // Rewind each stream | |
151 foreach ($this->streams as $i => $stream) { | |
152 try { | |
153 $stream->rewind(); | |
154 } catch (\Exception $e) { | |
155 throw new \RuntimeException('Unable to seek stream ' | |
156 . $i . ' of the AppendStream', 0, $e); | |
157 } | |
158 } | |
159 | |
160 // Seek to the actual position by reading from each stream | |
161 while ($this->pos < $offset && !$this->eof()) { | |
162 $result = $this->read(min(8096, $offset - $this->pos)); | |
163 if ($result === '') { | |
164 break; | |
165 } | |
166 } | |
167 } | |
168 | |
169 /** | |
170 * Reads from all of the appended streams until the length is met or EOF. | |
171 * | |
172 * {@inheritdoc} | |
173 */ | |
174 public function read($length) | |
175 { | |
176 $buffer = ''; | |
177 $total = count($this->streams) - 1; | |
178 $remaining = $length; | |
179 $progressToNext = false; | |
180 | |
181 while ($remaining > 0) { | |
182 | |
183 // Progress to the next stream if needed. | |
184 if ($progressToNext || $this->streams[$this->current]->eof()) { | |
185 $progressToNext = false; | |
186 if ($this->current === $total) { | |
187 break; | |
188 } | |
189 $this->current++; | |
190 } | |
191 | |
192 $result = $this->streams[$this->current]->read($remaining); | |
193 | |
194 // Using a loose comparison here to match on '', false, and null | |
195 if ($result == null) { | |
196 $progressToNext = true; | |
197 continue; | |
198 } | |
199 | |
200 $buffer .= $result; | |
201 $remaining = $length - strlen($buffer); | |
202 } | |
203 | |
204 $this->pos += strlen($buffer); | |
205 | |
206 return $buffer; | |
207 } | |
208 | |
209 public function isReadable() | |
210 { | |
211 return true; | |
212 } | |
213 | |
214 public function isWritable() | |
215 { | |
216 return false; | |
217 } | |
218 | |
219 public function isSeekable() | |
220 { | |
221 return $this->seekable; | |
222 } | |
223 | |
224 public function write($string) | |
225 { | |
226 throw new \RuntimeException('Cannot write to an AppendStream'); | |
227 } | |
228 | |
229 public function getMetadata($key = null) | |
230 { | |
231 return $key ? null : []; | |
232 } | |
233 } |