[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/guzzlehttp/psr7/src/ -> CachingStream.php (source)

   1  <?php
   2  
   3  namespace GuzzleHttp\Psr7;
   4  
   5  use Psr\Http\Message\StreamInterface;
   6  
   7  /**
   8   * Stream decorator that can cache previously read bytes from a sequentially
   9   * read stream.
  10   *
  11   * @final
  12   */
  13  class CachingStream implements StreamInterface
  14  {
  15      use StreamDecoratorTrait;
  16  
  17      /** @var StreamInterface Stream being wrapped */
  18      private $remoteStream;
  19  
  20      /** @var int Number of bytes to skip reading due to a write on the buffer */
  21      private $skipReadBytes = 0;
  22  
  23      /**
  24       * We will treat the buffer object as the body of the stream
  25       *
  26       * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream.
  27       * @param StreamInterface $target Optionally specify where data is cached
  28       */
  29      public function __construct(
  30          StreamInterface $stream,
  31          StreamInterface $target = null
  32      ) {
  33          $this->remoteStream = $stream;
  34          $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));
  35      }
  36  
  37      public function getSize()
  38      {
  39          $remoteSize = $this->remoteStream->getSize();
  40  
  41          if (null === $remoteSize) {
  42              return null;
  43          }
  44  
  45          return max($this->stream->getSize(), $remoteSize);
  46      }
  47  
  48      public function rewind()
  49      {
  50          $this->seek(0);
  51      }
  52  
  53      public function seek($offset, $whence = SEEK_SET)
  54      {
  55          if ($whence == SEEK_SET) {
  56              $byte = $offset;
  57          } elseif ($whence == SEEK_CUR) {
  58              $byte = $offset + $this->tell();
  59          } elseif ($whence == SEEK_END) {
  60              $size = $this->remoteStream->getSize();
  61              if ($size === null) {
  62                  $size = $this->cacheEntireStream();
  63              }
  64              $byte = $size + $offset;
  65          } else {
  66              throw new \InvalidArgumentException('Invalid whence');
  67          }
  68  
  69          $diff = $byte - $this->stream->getSize();
  70  
  71          if ($diff > 0) {
  72              // Read the remoteStream until we have read in at least the amount
  73              // of bytes requested, or we reach the end of the file.
  74              while ($diff > 0 && !$this->remoteStream->eof()) {
  75                  $this->read($diff);
  76                  $diff = $byte - $this->stream->getSize();
  77              }
  78          } else {
  79              // We can just do a normal seek since we've already seen this byte.
  80              $this->stream->seek($byte);
  81          }
  82      }
  83  
  84      public function read($length)
  85      {
  86          // Perform a regular read on any previously read data from the buffer
  87          $data = $this->stream->read($length);
  88          $remaining = $length - strlen($data);
  89  
  90          // More data was requested so read from the remote stream
  91          if ($remaining) {
  92              // If data was written to the buffer in a position that would have
  93              // been filled from the remote stream, then we must skip bytes on
  94              // the remote stream to emulate overwriting bytes from that
  95              // position. This mimics the behavior of other PHP stream wrappers.
  96              $remoteData = $this->remoteStream->read(
  97                  $remaining + $this->skipReadBytes
  98              );
  99  
 100              if ($this->skipReadBytes) {
 101                  $len = strlen($remoteData);
 102                  $remoteData = substr($remoteData, $this->skipReadBytes);
 103                  $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
 104              }
 105  
 106              $data .= $remoteData;
 107              $this->stream->write($remoteData);
 108          }
 109  
 110          return $data;
 111      }
 112  
 113      public function write($string)
 114      {
 115          // When appending to the end of the currently read stream, you'll want
 116          // to skip bytes from being read from the remote stream to emulate
 117          // other stream wrappers. Basically replacing bytes of data of a fixed
 118          // length.
 119          $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
 120          if ($overflow > 0) {
 121              $this->skipReadBytes += $overflow;
 122          }
 123  
 124          return $this->stream->write($string);
 125      }
 126  
 127      public function eof()
 128      {
 129          return $this->stream->eof() && $this->remoteStream->eof();
 130      }
 131  
 132      /**
 133       * Close both the remote stream and buffer stream
 134       */
 135      public function close()
 136      {
 137          $this->remoteStream->close() && $this->stream->close();
 138      }
 139  
 140      private function cacheEntireStream()
 141      {
 142          $target = new FnStream(['write' => 'strlen']);
 143          Utils::copyToStream($this, $target);
 144  
 145          return $this->tell();
 146      }
 147  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1