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
 * Wrapper class for PHP stream that supports read operations.
22
 *
23
 * @package phing.system.io
24
 */
25
class InputStream
26
{
27

28
    /**
29
     * @var resource The attached PHP stream.
30
     */
31
    protected $stream;
32

33
    /**
34
     * @var int Position of stream cursor.
35
     */
36
    protected $currentPosition = 0;
37

38
    /**
39
     * @var int Marked position of stream cursor.
40
     */
41
    protected $mark = 0;
42

43
    /**
44
     * Construct a new InputStream.
45
     *
46
     * @param  resource $stream Configured PHP stream for writing.
47
     * @throws IOException
48
     */
49 1
    public function __construct($stream)
50
    {
51 1
        if (!is_resource($stream)) {
52 0
            throw new IOException("Passed argument is not a valid stream.");
53
        }
54 1
        $this->stream = $stream;
55
    }
56

57
    /**
58
     * Skip over $n bytes.
59
     *
60
     * @param  int $n
61
     * @return int
62
     */
63 0
    public function skip($n)
64
    {
65 0
        $start = $this->currentPosition;
66

67 0
        $ret = @fseek($this->stream, $n, SEEK_CUR);
68 0
        if ($ret === -1) {
69 0
            return -1;
70
        }
71

72 0
        $this->currentPosition = ftell($this->stream);
73

74 0
        if ($start > $this->currentPosition) {
75 0
            $skipped = $start - $this->currentPosition;
76
        } else {
77 0
            $skipped = $this->currentPosition - $start;
78
        }
79

80 0
        return $skipped;
81
    }
82

83
    /**
84
     * Read data from stream until $len chars or EOF.
85
     *
86
     * @param  int $len Num chars to read.  If not specified this stream will read until EOF.
87
     * @return mixed chars read or -1 if eof.
88
     */
89 1
    public function read($len = null)
90
    {
91 1
        if ($this->eof()) {
92 1
            return -1;
93
        }
94

95 1
        if ($len === null) { // we want to keep reading until we get an eof
96 1
            $out = "";
97 1
            while (!$this->eof()) {
98 1
                $out .= fread($this->stream, 8192);
99 1
                $this->currentPosition = ftell($this->stream);
100
            }
101
        } else {
102 1
            $out = fread($this->stream, $len); // adding 1 seems to ensure that next call to read() will return EOF (-1)
103 1
            $this->currentPosition = ftell($this->stream);
104
        }
105

106 1
        return $out;
107
    }
108

109
    /**
110
     * Marks the current position in this input stream.
111
     *
112
     * @throws IOException - if the underlying stream doesn't support this method.
113
     */
114 0
    public function mark()
115
    {
116 0
        if (!$this->markSupported()) {
117 0
            throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
118
        }
119 0
        $this->mark = $this->currentPosition;
120
    }
121

122
    /**
123
     * Whether the input stream supports mark and reset methods.
124
     *
125
     * @return boolean
126
     */
127 0
    public function markSupported()
128
    {
129 0
        return false;
130
    }
131

132
    /**
133
     * Repositions this stream to the position at the time the mark method was last called on this input stream.
134
     *
135
     * @throws IOException - if the underlying stream doesn't support this method.
136
     */
137 0
    public function reset()
138
    {
139 0
        if (!$this->markSupported()) {
140 0
            throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
141
        }
142
        // goes back to last mark, by default this would be 0 (i.e. rewind file).
143 0
        fseek($this->stream, SEEK_SET, $this->mark);
144 0
        $this->mark = 0;
145
    }
146

147
    /**
148
     * Closes stream.
149
     *
150
     * @throws IOException if stream cannot be closed (note that calling close() on an already-closed stream will not raise an exception)
151
     */
152 1
    public function close()
153
    {
154 1
        if ($this->stream === null) {
155 0
            return;
156
        }
157 1
        error_clear_last();
158 1
        if (false === @fclose($this->stream)) {
159 0
            $lastError = error_get_last();
160 0
            $errormsg = $lastError['message'];
161
            // FAILED.
162 0
            $msg = "Cannot fclose " . $this->__toString() . " $errormsg";
163 0
            throw new IOException($msg);
164
        }
165 1
        $this->stream = null;
166
    }
167

168
    /**
169
     * Whether eof has been reached with stream.
170
     *
171
     * @return boolean
172
     */
173 1
    public function eof()
174
    {
175 1
        return feof($this->stream);
176
    }
177

178
    /**
179
     * Returns string representation of attached stream.
180
     *
181
     * @return string
182
     */
183 0
    public function __toString()
184
    {
185 0
        return (string) $this->stream;
186
    }
187
}

Read our documentation on viewing source code .

Loading