Passed
Push — master ( 33b6d3...80c378 )
by Siad
05:33
created

BufferedReader::readLine()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.025

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 6
nop 0
dl 0
loc 17
ccs 9
cts 10
cp 0.9
crap 5.025
rs 9.6111
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * Convenience class for reading files.
22
 *
23
 * @author <a href="mailto:[email protected]">Yannick Lecaillez</a>
24
 *
25
 * @see FilterReader
26
 *
27
 * @package phing.system.io
28
 */
29
class BufferedReader extends Reader
30
{
31
    private $bufferSize = 0;
32
    private $buffer = null;
33
    private $bufferPos = 0;
34
35
    /**
36
     * The Reader we are buffering for.
37
     *
38
     * @var InputStreamReader
39
     */
40
    private $in;
41
42
    /**
43
     *
44
     * @param InputStreamReader $reader The reader (e.g. FileReader).
45
     * @param integer $buffsize The size of the buffer we should use for reading files.
46
     *                                    A large buffer ensures that most files (all scripts?)
47
     *                                    are parsed in 1 buffer.
48
     */
49 837
    public function __construct(InputStreamReader $reader, $buffsize = 65536)
50
    {
51 837
        $this->in = $reader;
52 837
        $this->bufferSize = $buffsize;
53 837
    }
54
55
    /**
56
     * Reads and returns a chunk of data.
57
     *
58
     * @param  int $len Number of bytes to read.  Default is to read configured buffer size number of bytes.
59
     * @return mixed buffer or -1 if EOF.
60
     */
61 837
    public function read($len = null)
62
    {
63
64
        // if $len is specified, we'll use that; otherwise, use the configured buffer size.
65 837
        if ($len === null) {
66 837
            $len = $this->bufferSize;
67
        }
68
69 837
        if (($data = $this->in->read($len)) !== -1) {
70
            // not all files end with a newline character, so we also need to check EOF
71 837
            if (!$this->in->eof()) {
72 5
                $notValidPart = strrchr($data, "\n");
73 5
                $notValidPartSize = strlen($notValidPart);
74
75 5
                if ($notValidPartSize > 1) {
76
                    // Block doesn't finish on a EOL
77
                    // Find the last EOL and forget all following stuff
78
                    $dataSize = strlen($data);
79
                    $validSize = $dataSize - $notValidPartSize + 1;
80
81
                    $data = substr($data, 0, $validSize);
82
83
                    // Rewind to the beginning of the forgotten stuff.
84
                    $this->in->skip(-$notValidPartSize + 1);
85
                }
86
            } // if !EOF
87
        }
88
89 837
        return $data;
90
    }
91
92
    /**
93
     * @param int $n
94
     * @return int
95
     */
96
    public function skip($n)
97
    {
98
        return $this->in->skip($n);
99
    }
100
101
    public function reset()
102
    {
103
        $this->in->reset();
104
    }
105
106 837
    public function close()
107
    {
108 837
        $this->in->close();
109 837
    }
110
111
    /**
112
     * Read a line from input stream.
113
     */
114 4
    public function readLine()
115
    {
116 4
        $line = null;
117 4
        while (($ch = $this->readChar()) !== -1) {
118 4
            if ($ch === "\n") {
119 3
                $line = rtrim($line);
0 ignored issues
show
Bug introduced by
It seems like $line can also be of type null; however, parameter $string of rtrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
                $line = rtrim(/** @scrutinizer ignore-type */ $line);
Loading history...
120 3
                break;
121
            }
122 4
            $line .= $ch;
123
        }
124
125
        // Warning : Not considering an empty line as an EOF
126 4
        if ($line === null && $ch !== -1) {
127
            return "";
128
        }
129
130 4
        return $line;
131
    }
132
133
    /**
134
     * Reads a single char from the reader.
135
     *
136
     * @return string single char or -1 if EOF.
137
     */
138 4
    public function readChar()
139
    {
140 4
        if ($this->buffer === null) {
141
            // Buffer is empty, fill it ...
142 4
            $read = $this->in->read($this->bufferSize);
143 4
            if ($read === -1) {
144 4
                $ch = -1;
145
            } else {
146 4
                $this->buffer = $read;
147
148 4
                return $this->readChar(); // recurse
149
            }
150
        } else {
151
            // Get next buffered char ...
152
            // handle case where buffer is read-in, but is empty.  The next readChar() will return -1 EOF,
153
            // so we just return empty string (char) at this point.  (Probably could also return -1 ...?)
154 4
            $ch = ($this->buffer !== "") ? $this->buffer[$this->bufferPos] : '';
155 4
            $this->bufferPos++;
156 4
            if ($this->bufferPos >= strlen($this->buffer)) {
157 4
                $this->buffer = null;
158 4
                $this->bufferPos = 0;
159
            }
160
        }
161
162 4
        return $ch;
163
    }
164
165
    /**
166
     * Returns whether eof has been reached in stream.
167
     * This is important, because filters may want to know if the end of the file (and not just buffer)
168
     * has been reached.
169
     *
170
     * @return boolean
171
     */
172 837
    public function eof()
173
    {
174 837
        return $this->in->eof();
175
    }
176
177
    /**
178
     * @return string
179
     */
180 837
    public function getResource()
181
    {
182 837
        return $this->in->getResource();
183
    }
184
}
185