Passed
Push — master ( 35a69c...54bf96 )
by Ryuichi
01:46
created

StringInputStream   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Test Coverage

Coverage 89.29%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 57
c 1
b 0
f 0
dl 0
loc 160
ccs 50
cts 56
cp 0.8929
rs 10
wmc 20

7 Methods

Rating   Name   Duplication   Size   Complexity  
A close() 0 3 1
A __construct() 0 4 1
A skip() 0 29 4
A isMarkSupported() 0 3 1
A readLine() 0 29 5
A eof() 0 3 1
B read() 0 41 7
1
<?php
2
3
namespace WebStream\IO;
4
5
use WebStream\Exception\Extend\InvalidArgumentException;
0 ignored issues
show
Bug introduced by
The type WebStream\Exception\Exte...nvalidArgumentException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use WebStream\Exception\Extend\IOException;
0 ignored issues
show
Bug introduced by
The type WebStream\Exception\Extend\IOException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
8
/**
9
 * StringInputStream
10
 * @author Ryuichi TANAKA.
11
 * @since 2016/02/07
12
 * @version 0.7
13
 */
14
class StringInputStream extends InputStream
15
{
16
    /**
17
     * @var int 文字列長
18
     */
19
    private $length;
20
21
    /**
22
     * @var bool 終端かどうか
23
     */
24
    private $isEOF = false;
25
26
    /**
27
     * construct
28
     * @param string $str 文字列
29
     */
30
    public function __construct($str)
31
    {
32
        parent::__construct($str);
33
        $this->length = strlen($str);
34
    }
35
36
    /**
37
     * 入力ストリームを閉じる
38
     */
39 20
    public function close()
40
    {
41 20
        $this->stream = null;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 17
    public function read($length = null)
48
    {
49 17
        if ($this->stream === null) {
50 1
            return null;
51
        }
52
53 16
        if ($this->eof()) {
54 2
            return null;
55
        }
56
57
        // SkipでポインタをずらしただけではEOFにはならない、FileInputStream実装に合わせる
58
        // Skipでずらしたあとreadすると空文字を返し、もう一度readするとEOFを認識する
59
        // ファイルの終端より先にポインタをすすめることは「可能」=書き込みと同じ
60
        // なので、現在の終端位置より先に進めてもEOF自体にはならない。進めた位置はEOFのひとつ前
61
        // だからもう一回readするとEOFに到達する。なのでskipを使ってもEOF到達できない
62 16
        if ($this->cursorPosition > $this->length - 1) {
63 4
            $this->isEOF = true;
64
65 4
            return "";
66
        }
67
68
        $out = "";
69 12
        if ($length === null) {
70
            $length = 1;
0 ignored issues
show
Unused Code introduced by
The assignment to $length is dead and can be removed.
Loading history...
71 7
            $out = substr($this->stream, $this->cursorPosition, 1);
72 7
            $this->cursorPosition += 1;
73
        } else {
74 5
            if (!is_int($length)) {
75 1
                throw new InvalidArgumentException("Stream read must be a numeric value.");
76
            }
77
78
            // $lengthがファイル終端を越えないようにする
79 4
            if (($this->cursorPosition + $length) > $this->length) {
80 2
                $length = $this->length - $this->cursorPosition;
81
            }
82
83 4
            $out = substr($this->stream, $this->cursorPosition, $length);
84 4
            $this->cursorPosition += $length;
85
        }
86
87 11
        return $out;
88
    }
89
90
    /**
91
     * 入力ストリームから行単位でデータを読み込む
92
     * 末尾に改行コードは含まない
93
     * @return string 読み込みデータ
94
     */
95 1
    public function readLine()
96
    {
97 1
        if ($this->stream === null) {
98
            return null;
99
        }
100
101 1
        if ($this->eof()) {
102
            return null;
103
        }
104
105
        // 処理対象の残りのバイト数
106 1
        $targetLength = $this->length - $this->cursorPosition;
107
108
        // 処理対象の文字列
109 1
        $text = substr($this->stream, $this->cursorPosition, $targetLength);
110 1
        $lengthEOL = strlen(PHP_EOL);
111 1
        $notLinePart = strstr($text, PHP_EOL);
112
113 1
        $notLinePartLength = 0;
114 1
        if ($notLinePart !== false) {
115 1
            $notLinePartLength = strlen($notLinePart);
116
        }
117
118 1
        $offset = $targetLength - $notLinePartLength;
119 1
        $out = substr($text, 0, $offset);
120 1
        $out = $out === false ? null : $out;
121 1
        $this->skip($offset + $lengthEOL);
122
123 1
        return $out;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 14
    public function skip(int $pos)
130
    {
131 14
        if ($this->stream === null) {
132
            return -1;
133
        }
134
135
        // ファイル終端到達後、skipを実行すると後方にポインタが移動する
136
        // このときEOFだったものがEOFでなくなる
137 14
        $start = $this->cursorPosition;
138
139
        // 現在位置が負になった場合は-1を返して終了
140 14
        if ($this->cursorPosition + $pos < 0) {
141 2
            return -1;
142
        }
143
144 12
        $this->cursorPosition += $pos;
145 12
        $this->isEOF = false;
146
147
        // skipした実際のバイト数
148
        $skipNum = 0;
149 12
        if ($start > $this->cursorPosition) {
150
            // 後方へ移動
151 1
            $skipNum = $start - $this->cursorPosition;
152
        } else {
153
            // 前方へ移動
154 12
            $skipNum = $this->cursorPosition - $start;
155
        }
156
157 12
        return $skipNum;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 17
    public function eof()
164
    {
165 17
        return $this->isEOF;
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171 2
    public function isMarkSupported()
172
    {
173 2
        return true;
174
    }
175
}
176