GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( bfe104...7d2154 )
by Colin
7s
created

Cursor::advanceBy()   D

↳ Parent: Cursor

Complexity

Conditions 10
Paths 70

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 32
Code Lines 23

Code Coverage

Tests 25
CRAP Score 10

Importance

Changes 7
Bugs 4 Features 0
Metric Value
c 7
b 4
f 0
dl 0
loc 32
ccs 25
cts 25
cp 1
rs 4.8196
cc 10
eloc 23
nc 70
nop 2
crap 10

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace League\CommonMark;
13
14
class Cursor
15
{
16
    const INDENT_LEVEL = 4;
17
18
    /**
19
     * @var string
20
     */
21
    private $line;
22
23
    /**
24
     * @var int
25
     */
26
    private $length;
27
28
    /**
29
     * @var int
30
     *
31
     * It's possible for this to be 1 char past the end, meaning we've parsed all chars and have
32
     * reached the end.  In this state, any character-returning method MUST return null.
33
     */
34
    private $currentPosition = 0;
35
36
    /**
37
     * @var int
38
     */
39
    private $column = 0;
40
41
    /**
42
     * @var int
43
     */
44
    private $indent = 0;
45
46
    /**
47
     * @var int
48
     */
49
    private $previousPosition = 0;
50
51
    /**
52
     * @var int|null
53
     */
54
    private $firstNonSpaceCache;
55
56
    /**
57
     * @var bool
58
     */
59
    private $partiallyConsumedTab = false;
60
61
    /**
62
     * @param string $line
63
     */
64 2301
    public function __construct($line)
65
    {
66 2301
        $this->line = $line;
67 2301
        $this->length = mb_strlen($line, 'utf-8');
68 2301
    }
69
70
    /**
71
     * Returns the position of the next non-space character
72
     *
73
     * @return int
74
     */
75 1989
    public function getFirstNonSpacePosition()
76
    {
77 1989
        if ($this->firstNonSpaceCache !== null) {
78 1863
            return $this->firstNonSpaceCache;
79
        }
80
81 1989
        $i = $this->currentPosition;
82 1989
        $cols = $this->column;
83
84 1989
        while (($c = $this->getCharacter($i)) !== null) {
85 1974
            if ($c === ' ') {
86 468
                $i++;
87 468
                $cols++;
88 1974
            } elseif ($c === "\t") {
89 30
                $i++;
90 30
                $cols += (4 - ($cols % 4));
91 30
            } else {
92 1941
                break;
93
            }
94 483
        }
95
96 1989
        $nextNonSpace = ($c === null) ? $this->length : $i;
97 1989
        $this->indent = $cols - $this->column;
98
99 1989
        return $this->firstNonSpaceCache = $nextNonSpace;
100
    }
101
102
    /**
103
     * Returns the next character which isn't a space
104
     *
105
     * @return string
106
     */
107 1836
    public function getFirstNonSpaceCharacter()
108
    {
109 1836
        return $this->getCharacter($this->getFirstNonSpacePosition());
110
    }
111
112
    /**
113
     * Calculates the current indent (number of spaces after current position)
114
     *
115
     * @return int
116
     */
117 1923
    public function getIndent()
118
    {
119 1923
        $this->getFirstNonSpacePosition();
120
121 1923
        return $this->indent;
122
    }
123
124
    /**
125
     * Whether the cursor is indented to INDENT_LEVEL
126
     *
127
     * @return bool
128
     */
129 1863
    public function isIndented()
130
    {
131 1863
        return $this->getIndent() >= self::INDENT_LEVEL;
132
    }
133
134
    /**
135
     * @param int|null $index
136
     *
137
     * @return string|null
138
     */
139 2082
    public function getCharacter($index = null)
140
    {
141 2082
        if ($index === null) {
142 1617
            $index = $this->currentPosition;
143 1617
        }
144
145
        // Index out-of-bounds, or we're at the end
146 2082
        if ($index < 0 || $index >= $this->length) {
147 1803
            return;
148
        }
149
150 2049
        return mb_substr($this->line, $index, 1, 'utf-8');
151
    }
152
153
    /**
154
     * Returns the next character (or null, if none) without advancing forwards
155
     *
156
     * @param int $offset
157
     *
158
     * @return string|null
159
     */
160 987
    public function peek($offset = 1)
161
    {
162 987
        return $this->getCharacter($this->currentPosition + $offset);
163
    }
164
165
    /**
166
     * Whether the remainder is blank
167
     *
168
     * @return bool
169
     */
170 1881
    public function isBlank()
171
    {
172 1881
        return $this->getFirstNonSpacePosition() === $this->length;
173
    }
174
175
    /**
176
     * Move the cursor forwards
177
     */
178 756
    public function advance()
179
    {
180 756
        $this->advanceBy(1);
181 756
    }
182
183
    /**
184
     * Move the cursor forwards
185
     *
186
     * @param int $characters Number of characters to advance by
187
     */
188 2124
    public function advanceBy($characters, $advanceByColumns = false)
189
    {
190 2124
        $this->previousPosition = $this->currentPosition;
191 2124
        $this->firstNonSpaceCache = null;
192
193 2124
        $nextFewChars = mb_substr($this->line, $this->currentPosition, $characters, 'utf-8');
194 2124
        if ($characters === 1 && !empty($nextFewChars)) {
195 1389
            $asArray = [$nextFewChars];
196 1389
        } else {
197 2010
            $asArray = preg_split('//u', $nextFewChars, null, PREG_SPLIT_NO_EMPTY);
198
        }
199
200 2124
        foreach ($asArray as $relPos => $c) {
201 2040
            if ($c === "\t") {
202 36
                $charsToTab = 4 - ($this->column % 4);
203 36
                $this->partiallyConsumedTab = $advanceByColumns && $charsToTab > $characters;
204 36
                $charsToAdvance = $charsToTab > $characters ? $characters : $charsToTab;
205 36
                $this->column += $charsToAdvance;
206 36
                $this->currentPosition += $this->partiallyConsumedTab ? 0 : 1;
207 36
                $characters -= ($advanceByColumns ? $charsToAdvance : 1);
208 36
            } else {
209 2037
                $this->partiallyConsumedTab = false;
210 2037
                $this->currentPosition++;
211 2037
                $this->column++;
212 2037
                $characters--;
213
            }
214
215 2040
            if ($characters <= 0) {
216 2034
                break;
217
            }
218 2124
        }
219 2124
    }
220
221
    /**
222
     * Advances the cursor by a single space or tab, if present
223
     *
224
     * @return bool
225
     */
226 336
    public function advanceBySpaceOrTab()
227
    {
228 336
        $character = $this->getCharacter();
229
230 336
        if ($character === ' ' || $character === "\t") {
231 321
            $this->advanceBy(1, true);
232
233 321
            return true;
234
        }
235
236 252
        return false;
237
    }
238
239
    /**
240
     * Advances the cursor while the given character is matched
241
     *
242
     * @param string   $character                  Character to match
243
     * @param int|null $maximumCharactersToAdvance Maximum number of characters to advance before giving up
244
     *
245
     * @return int Number of positions moved (0 if unsuccessful)
246
     */
247 144
    public function advanceWhileMatches($character, $maximumCharactersToAdvance = null)
248
    {
249
        // Calculate how far to advance
250 144
        $start = $this->currentPosition;
251 144
        $newIndex = $start;
252 144
        if ($maximumCharactersToAdvance === null) {
253 18
            $maximumCharactersToAdvance = $this->length;
254 18
        }
255
256 144
        $max = min($start + $maximumCharactersToAdvance, $this->length);
257
258 144
        while ($newIndex < $max && $this->getCharacter($newIndex) === $character) {
259 45
            ++$newIndex;
260 45
        }
261
262 144
        if ($newIndex <= $start) {
263 108
            return 0;
264
        }
265
266 45
        $this->advanceBy($newIndex - $start);
267
268 45
        return $this->currentPosition - $this->previousPosition;
269
    }
270
271
    /**
272
     * Parse zero or more space characters, including at most one newline
273
     *
274
     * @return int Number of positions moved
275
     */
276 1872
    public function advanceToFirstNonSpace()
277
    {
278 1872
        $matches = [];
279 1872
        preg_match('/^ *(?:\n *)?/', $this->getRemainder(), $matches, PREG_OFFSET_CAPTURE);
280
281
        // [0][0] contains the matched text
282
        // [0][1] contains the index of that match
283 1872
        $increment = $matches[0][1] + strlen($matches[0][0]);
284
285 1872
        if ($increment === 0) {
286 1809
            return 0;
287
        }
288
289 468
        $this->advanceBy($increment);
290
291 468
        return $this->currentPosition - $this->previousPosition;
292
    }
293
294
    /**
295
     * @return string
296
     */
297 1965
    public function getRemainder()
298
    {
299 1965
        if ($this->isAtEnd()) {
300 660
            return '';
301
        }
302
303 1953
        $prefix = '';
304 1953
        $position = $this->currentPosition;
305 1953
        if ($this->partiallyConsumedTab) {
306 12
            $position++;
307 12
            $charsToTab = 4 - ($this->column % 4);
308 12
            $prefix = str_repeat(' ', $charsToTab);
309 12
        }
310
311 1953
        return $prefix . mb_substr($this->line, $position, null, 'utf-8');
312
    }
313
314
    /**
315
     * @return string
316
     */
317 1818
    public function getLine()
318
    {
319 1818
        return $this->line;
320
    }
321
322
    /**
323
     * @return bool
324
     */
325 1986
    public function isAtEnd()
326
    {
327 1986
        return $this->currentPosition >= $this->length;
328
    }
329
330
    /**
331
     * Try to match a regular expression
332
     *
333
     * Returns the matching text and advances to the end of that match
334
     *
335
     * @param string $regex
336
     *
337
     * @return string|null
338
     */
339 1833
    public function match($regex)
340
    {
341 1833
        $subject = $this->getRemainder();
342
343 1833
        $matches = [];
344 1833
        if (!preg_match($regex, $subject, $matches, PREG_OFFSET_CAPTURE)) {
345 1695
            return;
346
        }
347
348
        // PREG_OFFSET_CAPTURE always returns the byte offset, not the char offset, which is annoying
349 1716
        $offset = mb_strlen(mb_strcut($subject, 0, $matches[0][1], 'utf-8'), 'utf-8');
350
351
        // [0][0] contains the matched text
352
        // [0][1] contains the index of that match
353 1716
        $this->advanceBy($offset + mb_strlen($matches[0][0], 'utf-8'));
354
355 1716
        return $matches[0][0];
356
    }
357
358
    /**
359
     * @return CursorState
360
     */
361 1776
    public function saveState()
362
    {
363 1776
        return new CursorState(
364 1776
            $this->line,
365 1776
            $this->length,
366 1776
            $this->currentPosition,
367 1776
            $this->previousPosition,
368 1776
            $this->firstNonSpaceCache,
369 1776
            $this->indent,
370 1776
            $this->column
371 1776
        );
372
    }
373
374
    /**
375
     * @param CursorState $state
376
     */
377 1695
    public function restoreState(CursorState $state)
378
    {
379 1695
        $this->line = $state->getLine();
380 1695
        $this->length = $state->getLength();
381 1695
        $this->currentPosition = $state->getCurrentPosition();
382 1695
        $this->previousPosition = $state->getPreviousPosition();
383 1695
        $this->firstNonSpaceCache = $state->getFirstNonSpaceCache();
384 1695
        $this->column = $state->getColumn();
385 1695
        $this->indent = $state->getIndent();
386 1695
    }
387
388
    /**
389
     * @return int
390
     */
391 588
    public function getPosition()
392
    {
393 588
        return $this->currentPosition;
394
    }
395
396
    /**
397
     * @return string
398
     */
399 810
    public function getPreviousText()
400
    {
401 810
        return mb_substr($this->line, $this->previousPosition, $this->currentPosition - $this->previousPosition, 'utf-8');
402
    }
403
404
    /**
405
     * @return int
406
     */
407 243
    public function getColumn()
408
    {
409 243
        return $this->column;
410
    }
411
}
412