BufferedReader.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. /*
  3. * $Id: BufferedReader.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. include_once 'phing/system/io/Reader.php';
  22. /**
  23. * Convenience class for reading files.
  24. *
  25. * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
  26. * @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
  27. * @access public
  28. * @see FilterReader
  29. * @package phing.system.io
  30. */
  31. class BufferedReader extends Reader {
  32. private $bufferSize = 0;
  33. private $buffer = null;
  34. private $bufferPos = 0;
  35. /**
  36. * The Reader we are buffering for.
  37. */
  38. private $in;
  39. /**
  40. *
  41. * @param object $reader The reader (e.g. FileReader).
  42. * @param integer $buffsize The size of the buffer we should use for reading files.
  43. * A large buffer ensures that most files (all scripts?) are parsed in 1 buffer.
  44. */
  45. function __construct(Reader $reader, $buffsize = 65536) {
  46. $this->in = $reader;
  47. $this->bufferSize = $buffsize;
  48. }
  49. /**
  50. * Reads and returns a chunk of data.
  51. * @param int $len Number of bytes to read. Default is to read configured buffer size number of bytes.
  52. * @return mixed buffer or -1 if EOF.
  53. */
  54. function read($len = null) {
  55. // if $len is specified, we'll use that; otherwise, use the configured buffer size.
  56. if ($len === null) $len = $this->bufferSize;
  57. if ( ($data = $this->in->read($len)) !== -1 ) {
  58. // not all files end with a newline character, so we also need to check EOF
  59. if (!$this->in->eof()) {
  60. $notValidPart = strrchr($data, "\n");
  61. $notValidPartSize = strlen($notValidPart);
  62. if ( $notValidPartSize > 1 ) {
  63. // Block doesn't finish on a EOL
  64. // Find the last EOL and forget all following stuff
  65. $dataSize = strlen($data);
  66. $validSize = $dataSize - $notValidPartSize + 1;
  67. $data = substr($data, 0, $validSize);
  68. // Rewind to the begining of the forgotten stuff.
  69. $this->in->skip(-$notValidPartSize+1);
  70. }
  71. } // if !EOF
  72. }
  73. return $data;
  74. }
  75. function skip($n) {
  76. return $this->in->skip($n);
  77. }
  78. function reset() {
  79. return $this->in->reset();
  80. }
  81. function close() {
  82. return $this->in->close();
  83. }
  84. function open() {
  85. return $this->in->open();
  86. }
  87. /**
  88. * Read a line from input stream.
  89. */
  90. function readLine() {
  91. $line = null;
  92. while ( ($ch = $this->readChar()) !== -1 ) {
  93. if ( $ch === "\n" ) {
  94. break;
  95. }
  96. $line .= $ch;
  97. }
  98. // Warning : Not considering an empty line as an EOF
  99. if ( $line === null && $ch !== -1 )
  100. return "";
  101. return $line;
  102. }
  103. /**
  104. * Reads a single char from the reader.
  105. * @return string single char or -1 if EOF.
  106. */
  107. function readChar() {
  108. if ( $this->buffer === null ) {
  109. // Buffer is empty, fill it ...
  110. $read = $this->in->read($this->bufferSize);
  111. if ($read === -1) {
  112. $ch = -1;
  113. } else {
  114. $this->buffer = $read;
  115. return $this->readChar(); // recurse
  116. }
  117. } else {
  118. // Get next buffered char ...
  119. // handle case where buffer is read-in, but is empty. The next readChar() will return -1 EOF,
  120. // so we just return empty string (char) at this point. (Probably could also return -1 ...?)
  121. $ch = ($this->buffer !== "") ? $this->buffer{$this->bufferPos} : '';
  122. $this->bufferPos++;
  123. if ( $this->bufferPos >= strlen($this->buffer) ) {
  124. $this->buffer = null;
  125. $this->bufferPos = 0;
  126. }
  127. }
  128. return $ch;
  129. }
  130. /**
  131. * Returns whether eof has been reached in stream.
  132. * This is important, because filters may want to know if the end of the file (and not just buffer)
  133. * has been reached.
  134. * @return boolean
  135. */
  136. function eof() {
  137. return $this->in->eof();
  138. }
  139. function getResource() {
  140. return $this->in->getResource();
  141. }
  142. }