StringBuffer   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
eloc 27
dl 0
loc 90
rs 10
c 2
b 1
f 1
wmc 15

10 Methods

Rating   Name   Duplication   Size   Complexity  
A prevSymbol() 0 9 3
A nextSymbol() 0 6 2
A __construct() 0 4 1
A resetToken() 0 3 1
A isEnd() 0 3 1
A finishToken() 0 3 1
A getSymbol() 0 6 2
A getTokenAsString() 0 3 1
A getTokenPosition() 0 3 1
A getTokenAsArray() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Remorhaz\UniLex\IO;
6
7
use Remorhaz\UniLex\Exception;
8
use Remorhaz\UniLex\Lexer\Token;
9
use Remorhaz\UniLex\Lexer\TokenPosition;
10
11
class StringBuffer implements CharBufferInterface, TokenExtractInterface
12
{
13
    private $data;
14
15
    private $length;
16
17
    private $startOffset = 0;
18
19
    private $previewOffset = 0;
20
21
    public function __construct(string $data)
22
    {
23
        $this->data = $data;
24
        $this->length = strlen($data);
25
    }
26
27
    public function isEnd(): bool
28
    {
29
        return $this->previewOffset == $this->length;
30
    }
31
32
    /**
33
     * @return int
34
     * @throws Exception
35
     */
36
    public function getSymbol(): int
37
    {
38
        if ($this->previewOffset == $this->length) {
39
            throw new Exception("No symbol to preview at index {$this->previewOffset}");
40
        }
41
        return ord($this->data[$this->previewOffset]);
42
    }
43
44
    /**
45
     * @throws Exception
46
     */
47
    public function nextSymbol(): void
48
    {
49
        if ($this->previewOffset == $this->length) {
50
            throw new Exception("Unexpected end of buffer on preview at index {$this->previewOffset}");
51
        }
52
        $this->previewOffset++;
53
    }
54
55
    /**
56
     * @param int $repeat
57
     * @throws Exception
58
     */
59
    public function prevSymbol(int $repeat = 1): void
60
    {
61
        if ($repeat < 1) {
62
            throw new Exception("Non-positive unread repeat counter: {$repeat}");
63
        }
64
        if ($this->previewOffset - $repeat < $this->startOffset) {
65
            throw new Exception("Invalid unread repeat counter: {$repeat}");
66
        }
67
        $this->previewOffset -= $repeat;
68
    }
69
70
    public function resetToken(): void
71
    {
72
        $this->previewOffset = $this->startOffset;
73
    }
74
75
    public function finishToken(Token $token): void
76
    {
77
        $this->startOffset = $this->previewOffset;
78
    }
79
80
    /**
81
     * @return TokenPosition
82
     * @throws Exception
83
     */
84
    public function getTokenPosition(): TokenPosition
85
    {
86
        return new TokenPosition($this->startOffset, $this->previewOffset);
87
    }
88
89
    public function getTokenAsString(): string
90
    {
91
        return substr($this->data, $this->startOffset, $this->previewOffset - $this->startOffset);
92
    }
93
94
    public function getTokenAsArray(): array
95
    {
96
        $result = [];
97
        for ($i = $this->startOffset; $i < $this->previewOffset; $i++) {
98
            $result[] = ord($this->data[$i]);
99
        }
100
        return $result;
101
    }
102
}
103