Completed
Push — master ( a91f17...e1c233 )
by Maik
01:59
created

MemoryStream::slurp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
crap 2
1
<?php
2
3
/**
4
 * This file is part of the PHP Generics package.
5
 *
6
 * @package Generics
7
 */
8
namespace Generics\Streams;
9
10
use Generics\Util\Interpolator;
11
12
/**
13
 * This class provides a memory stream for both input and output
14
 *
15
 * @author Maik Greubel <[email protected]>
16
 */
17
class MemoryStream implements InputOutputStream
18
{
19
    use Interpolator {
20
        interpolate as tinterpolate;
21
    }
22
23
    /**
24
     * The local memory buffer
25
     *
26
     * @var string
27
     */
28
    private $memory;
29
30
    /**
31
     * Current position in memory buffer
32
     *
33
     * @var int
34
     */
35
    private $current;
36
37
    /**
38
     * Whether it is possible to perform reading action
39
     *
40
     * @var boolean
41
     */
42
    private $ready;
43
44
    /**
45
     * Whether stream is closed
46
     *
47
     * @var boolean
48
     */
49
    private $closed;
50
51
    /**
52
     * Create a new MemoryStream
53
     *
54
     * @param InputStream $in
55
     *            optional existing input stream - will be copied
56
     */
57 50
    public function __construct(InputStream $in = null)
58
    {
59 50
        $this->memory = "";
60 50
        if ($in != null) {
61 2
            $copy = clone $in;
62 2
            $copy->reset();
63 2
            while ($copy->ready()) {
64 2
                $this->memory .= $copy->read();
65
            }
66 2
            $copy->close();
67
        }
68 50
        $this->current = 0;
69 50
        $this->ready = true;
70 50
        $this->closed = false;
71 50
    }
72
73
    /**
74
     *
75
     * {@inheritdoc}
76
     * @see \Generics\Streams\Stream::close()
77
     */
78 5
    public function close()
79
    {
80 5
        unset($this->memory);
81 5
        $this->current = 0;
82 5
        $this->ready = false;
83 5
        $this->closed = true;
84 5
    }
85
86
    /**
87
     *
88
     * {@inheritdoc}
89
     * @see \Generics\Streams\Stream::ready()
90
     */
91 38
    public function ready(): bool
92
    {
93 38
        return $this->ready;
94
    }
95
96
    /**
97
     *
98
     * {@inheritdoc}
99
     * @see \Generics\Streams\OutputStream::write()
100
     */
101 45
    public function write($buffer)
102
    {
103 45
        if ($this->closed) {
104 1
            throw new StreamException("Stream is not open");
105
        }
106 44
        $this->memory .= $buffer;
107 44
        $this->ready = true;
108 44
    }
109
110
    /**
111
     *
112
     * {@inheritdoc}
113
     * @see \Generics\Streams\InputStream::read()
114
     */
115 41
    public function read($length = 1, $offset = null): string
116
    {
117 41
        if ($this->closed) {
118 1
            throw new StreamException("Stream is not open");
119
        }
120
        
121 40
        if ($offset !== null) {
122
            $this->current = intval($offset);
123
        }
124
        
125 40
        if (strlen($this->memory) <= $this->current) {
126 21
            $this->ready = false;
127 21
            return "";
128
        }
129
        
130 39
        if (strlen($this->memory) - $this->current < $length) {
131 38
            $length = strlen($this->memory) - $this->current;
132
        }
133
        
134 39
        $out = substr($this->memory, $this->current, $length);
135 39
        $this->current += $length;
136
        
137 39
        if ($this->current == strlen($this->memory)) {
138 39
            $this->ready = false;
139
        }
140
        
141 39
        return $out;
142
    }
143
144
    /**
145
     *
146
     * {@inheritdoc}
147
     * @see \Countable::count()
148
     */
149 25
    public function count(): int
150
    {
151 25
        if ($this->closed) {
152 1
            throw new StreamException("Stream is not open");
153
        }
154 24
        if (! isset($this->memory)) {
155
            return 0;
156
        }
157 24
        return strlen($this->memory);
158
    }
159
160
    /**
161
     *
162
     * {@inheritdoc}
163
     * @see \Generics\Resettable::reset()
164
     */
165 28
    public function reset()
166
    {
167 28
        if ($this->closed) {
168 1
            throw new StreamException("Stream is not open");
169
        }
170 27
        $this->current = 0;
171 27
        $this->ready = true;
172 27
    }
173
174
    /**
175
     * Write to stream by interpolation of context vars into a string
176
     *
177
     * @param string $string
178
     *            The string to interpolate, may contains placeholders in format {placeholder}.
179
     * @param array $context
180
     *            The context array containing the associative replacers and its values.
181
     */
182 36
    public function interpolate($string, array $context)
183
    {
184 36
        $this->write($this->tinterpolate($string, $context));
185 36
    }
186
187
    /**
188
     *
189
     * {@inheritdoc}
190
     * @see \Generics\Streams\OutputStream::isWriteable()
191
     */
192 1
    public function isWriteable(): bool
193
    {
194 1
        return true;
195
    }
196
197
    /**
198
     *
199
     * {@inheritdoc}
200
     * @see \Generics\Streams\OutputStream::flush()
201
     */
202 6
    public function flush()
203
    {
204 6
        if ($this->closed) {
205 1
            throw new StreamException("Stream is not open");
206
        }
207
        
208 5
        unset($this->memory);
209 5
        $this->memory = "";
210 5
        $this->reset();
211 5
    }
212
213
    /**
214
     *
215
     * {@inheritdoc}
216
     * @see \Generics\Streams\Stream::isOpen()
217
     */
218
    public function isOpen(): bool
219
    {
220
        return true;
221
    }
222
223
    /**
224
     * Retrieve the whole memory string content
225
     * 
226
     * @return string
227
     */
228 1
    public function slurp(): string
229
    {
230 1
        $str = "";
231 1
        while ($this->ready()) {
232 1
            $str .= $this->read($this->count());
233
        }
234
        
235 1
        return $str;
236
    }
237
}
238