ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
CachingStream.php
Go to the documentation of this file.
1 <?php
2 namespace GuzzleHttp\Psr7;
3 
5 
11 {
13 
15  private $remoteStream;
16 
18  private $skipReadBytes = 0;
19 
26  public function __construct(
29  ) {
30  $this->remoteStream = $stream;
31  $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
32  }
33 
34  public function getSize()
35  {
36  return max($this->stream->getSize(), $this->remoteStream->getSize());
37  }
38 
39  public function rewind()
40  {
41  $this->seek(0);
42  }
43 
44  public function seek($offset, $whence = SEEK_SET)
45  {
46  if ($whence == SEEK_SET) {
47  $byte = $offset;
48  } elseif ($whence == SEEK_CUR) {
49  $byte = $offset + $this->tell();
50  } elseif ($whence == SEEK_END) {
51  $size = $this->remoteStream->getSize();
52  if ($size === null) {
53  $size = $this->cacheEntireStream();
54  }
55  $byte = $size + $offset;
56  } else {
57  throw new \InvalidArgumentException('Invalid whence');
58  }
59 
60  $diff = $byte - $this->stream->getSize();
61 
62  if ($diff > 0) {
63  // Read the remoteStream until we have read in at least the amount
64  // of bytes requested, or we reach the end of the file.
65  while ($diff > 0 && !$this->remoteStream->eof()) {
66  $this->read($diff);
67  $diff = $byte - $this->stream->getSize();
68  }
69  } else {
70  // We can just do a normal seek since we've already seen this byte.
71  $this->stream->seek($byte);
72  }
73  }
74 
75  public function read($length)
76  {
77  // Perform a regular read on any previously read data from the buffer
78  $data = $this->stream->read($length);
79  $remaining = $length - strlen($data);
80 
81  // More data was requested so read from the remote stream
82  if ($remaining) {
83  // If data was written to the buffer in a position that would have
84  // been filled from the remote stream, then we must skip bytes on
85  // the remote stream to emulate overwriting bytes from that
86  // position. This mimics the behavior of other PHP stream wrappers.
87  $remoteData = $this->remoteStream->read(
88  $remaining + $this->skipReadBytes
89  );
90 
91  if ($this->skipReadBytes) {
92  $len = strlen($remoteData);
93  $remoteData = substr($remoteData, $this->skipReadBytes);
94  $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
95  }
96 
97  $data .= $remoteData;
98  $this->stream->write($remoteData);
99  }
100 
101  return $data;
102  }
103 
104  public function write($string)
105  {
106  // When appending to the end of the currently read stream, you'll want
107  // to skip bytes from being read from the remote stream to emulate
108  // other stream wrappers. Basically replacing bytes of data of a fixed
109  // length.
110  $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
111  if ($overflow > 0) {
112  $this->skipReadBytes += $overflow;
113  }
114 
115  return $this->stream->write($string);
116  }
117 
118  public function eof()
119  {
120  return $this->stream->eof() && $this->remoteStream->eof();
121  }
122 
126  public function close()
127  {
128  $this->remoteStream->close() && $this->stream->close();
129  }
130 
131  private function cacheEntireStream()
132  {
133  $target = new FnStream(['write' => 'strlen']);
134  copy_to_stream($this, $target);
135 
136  return $this->tell();
137  }
138 }
Stream decorator that can cache previously read bytes from a sequentially read stream.
$size
Definition: RandomTest.php:84
rewind()
Seek to the beginning of the stream.
read($length)
Read data from the stream.
if($state['core:TerminatedAssocId'] !==null) $remaining
$stream
PHP stream implementation.
close()
Close both the remote stream and buffer stream.
getSize()
Get the size of the stream if known.
eof()
Returns true if the stream is at the end of the stream.
Compose stream implementations based on a hash of functions.
Definition: FnStream.php:12
copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen=-1)
Copy the contents of a stream into another stream until the given number of bytes have been read...
Definition: functions.php:369
__construct(StreamInterface $stream, StreamInterface $target=null)
We will treat the buffer object as the body of the stream.
$target
Definition: test.php:19
write($string)
Write data to the stream.
seek($offset, $whence=SEEK_SET)
Seek to a position in the stream.
tell()
Returns the current position of the file read/write pointer.
Describes a data stream.
$data
Definition: bench.php:6