InputStream.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /*
  3. * $Id: InputStream.php 905 2010-10-05 16:28:03Z mrook $
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information please see
  19. * <http://phing.info>.
  20. */
  21. /**
  22. * Wrapper class for PHP stream that supports read operations.
  23. *
  24. * @package phing.system.io
  25. */
  26. class InputStream {
  27. /**
  28. * @var resource The attached PHP stream.
  29. */
  30. protected $stream;
  31. /**
  32. * @var int Position of stream cursor.
  33. */
  34. protected $currentPosition = 0;
  35. /**
  36. * @var int Marked position of stream cursor.
  37. */
  38. protected $mark = 0;
  39. /**
  40. * Construct a new InputStream.
  41. * @param resource $stream Configured PHP stream for writing.
  42. */
  43. public function __construct($stream) {
  44. if (!is_resource($stream)) {
  45. throw new IOException("Passed argument is not a valid stream.");
  46. }
  47. $this->stream = $stream;
  48. }
  49. /**
  50. * Skip over $n bytes.
  51. * @param int $n
  52. */
  53. public function skip($n) {
  54. $start = $this->currentPosition;
  55. $ret = @fseek($this->stream, $n, SEEK_CUR);
  56. if ( $ret === -1 )
  57. return -1;
  58. $this->currentPosition = ftell($this->stream);
  59. if ( $start > $this->currentPosition )
  60. $skipped = $start - $this->currentPosition;
  61. else
  62. $skipped = $this->currentPosition - $start;
  63. return $skipped;
  64. }
  65. /**
  66. * Read data from stream until $len chars or EOF.
  67. * @param int $len Num chars to read. If not specified this stream will read until EOF.
  68. * @return string chars read or -1 if eof.
  69. */
  70. public function read($len = null) {
  71. if ($this->eof()) {
  72. return -1;
  73. }
  74. if ($len === null) { // we want to keep reading until we get an eof
  75. $out = "";
  76. while(!$this->eof()) {
  77. $out .= fread($this->stream, 8192);
  78. $this->currentPosition = ftell($this->stream);
  79. }
  80. } else {
  81. $out = fread($this->stream, $len); // adding 1 seems to ensure that next call to read() will return EOF (-1)
  82. $this->currentPosition = ftell($this->stream);
  83. }
  84. return $out;
  85. }
  86. /**
  87. * Marks the current position in this input stream.
  88. * @throws IOException - if the underlying stream doesn't support this method.
  89. */
  90. public function mark() {
  91. if (!$this->markSupported()) {
  92. throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
  93. }
  94. $this->mark = $this->currentPosition;
  95. }
  96. /**
  97. * Whether the input stream supports mark and reset methods.
  98. * @return boolean
  99. */
  100. public function markSupported() {
  101. return false;
  102. }
  103. /**
  104. * Repositions this stream to the position at the time the mark method was last called on this input stream.
  105. * @throws IOException - if the underlying stream doesn't support this method.
  106. */
  107. function reset() {
  108. if (!$this->markSupported()) {
  109. throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
  110. }
  111. // goes back to last mark, by default this would be 0 (i.e. rewind file).
  112. fseek($this->stream, SEEK_SET, $this->mark);
  113. $this->mark = 0;
  114. }
  115. /**
  116. * Closes stream.
  117. * @throws IOException if stream cannot be closed (note that calling close() on an already-closed stream will not raise an exception)
  118. */
  119. public function close() {
  120. if ($this->stream === null) {
  121. return;
  122. }
  123. if (false === @fclose($this->stream)) {
  124. // FAILED.
  125. $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg";
  126. throw new IOException($msg);
  127. }
  128. $this->stream = null;
  129. }
  130. /**
  131. * Whether eof has been reached with stream.
  132. * @return boolean
  133. */
  134. public function eof() {
  135. return feof($this->stream);
  136. }
  137. /**
  138. * Reads a entire until EOF and places contents in passed-in variable. Stream is closed after read.
  139. *
  140. * @param string &$rBuffer String variable where read contents will be put.
  141. * @return TRUE on success.
  142. * @author Charlie Killian, charlie@tizac.com
  143. * @throws IOException - if there is an error reading from stream.
  144. * @deprecated - Instead, use the read() method or a BufferedReader.
  145. */
  146. public function readInto(&$rBuffer) {
  147. $rBuffer = $this->read();
  148. $this->close();
  149. }
  150. /**
  151. * Returns string representation of attached stream.
  152. * @return string
  153. */
  154. public function __toString() {
  155. return (string) $this->stream;
  156. }
  157. }