Passed
Branch feature/first-release (43e0cc)
by Andrea Marco
10:48
created

State::callPointer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Cerbero\JsonParser;
4
5
use Cerbero\JsonParser\Pointers\Pointer;
6
use Cerbero\JsonParser\Pointers\Pointers;
7
use Cerbero\JsonParser\Tokens\Token;
8
use Cerbero\JsonParser\Tokens\Tokens;
9
10
/**
11
 * The JSON parsing state.
12
 *
13
 */
14
final class State
15
{
16
    /**
17
     * The JSON tree.
18
     *
19
     * @var Tree
20
     */
21
    private Tree $tree;
22
23
    /**
24
     * The JSON pointers.
25
     *
26
     * @var Pointers
27
     */
28
    private Pointers $pointers;
29
30
    /**
31
     * The JSON pointer matching the tree.
32
     *
33
     * @var Pointer
34
     */
35
    private Pointer $pointer;
36
37
    /**
38
     * The JSON buffer.
39
     *
40
     * @var string
41
     */
42
    private string $buffer = '';
43
44
    /**
45
     * Whether an object key is expected.
46
     *
47
     * @var bool
48
     */
49
    public bool $expectsKey = false;
50
51
    /**
52
     * The expected token.
53
     *
54
     * @var int
55
     */
56
    public int $expectedToken = Tokens::COMPOUND_BEGIN;
57
58
    /**
59
     * Instantiate the class.
60
     *
61
     */
62 134
    public function __construct()
63
    {
64 134
        $this->tree = new Tree();
65
    }
66
67
    /**
68
     * Retrieve the JSON tree
69
     *
70
     * @return Tree
71
     */
72 126
    public function tree(): Tree
73
    {
74 126
        return $this->tree;
75
    }
76
77
    /**
78
     * Determine whether the tree is deep
79
     *
80
     * @return bool
81
     */
82 124
    public function treeIsDeep(): bool
83
    {
84 124
        return $this->pointer == ''
0 ignored issues
show
introduced by
The condition $this->pointer == '' is always false.
Loading history...
85 38
            ? $this->tree->depth() > $this->pointer->depth()
86 124
            : $this->tree->depth() >= $this->pointer->depth();
87
    }
88
89
    /**
90
     * Retrieve the current key of the JSON tree
91
     *
92
     * @return string|int
93
     */
94 92
    public function key(): string|int
95
    {
96 92
        return $this->tree->currentKey();
97
    }
98
99
    /**
100
     * Set and match the given pointers
101
     *
102
     * @param Pointer ...$pointers
103
     * @return void
104
     */
105 130
    public function setPointers(Pointer ...$pointers): void
106
    {
107 130
        $this->pointers = new Pointers(...$pointers ?: [new Pointer('')]);
108
109 130
        $this->pointer = $this->pointers->matchTree($this->tree);
110
    }
111
112
    /**
113
     * Determine whether the parser can stop parsing
114
     *
115
     * @return bool
116
     */
117 123
    public function canStopParsing(): bool
118
    {
119 123
        return $this->pointers->wereFound() && !$this->pointer->includesTree($this->tree);
120
    }
121
122
    /**
123
     * Call the current pointer callback
124
     *
125
     * @param mixed $value
126
     * @param mixed $key
127
     * @return mixed
128
     */
129 91
    public function callPointer(mixed $value, mixed $key): mixed
130
    {
131 91
        return $this->pointer->call($value, $key);
132
    }
133
134
    /**
135
     * Mutate state depending on the given token
136
     *
137
     * @param Token $token
138
     * @return void
139
     */
140 126
    public function mutateByToken(Token $token): void
141
    {
142 126
        $this->tree->changed = false;
143 126
        $shouldTrackTree = $this->pointer == '' || $this->tree->depth() < $this->pointer->depth();
144
145 126
        if ($shouldTrackTree && $this->expectsKey) {
146 86
            $this->tree->traverseKey($token);
147 126
        } elseif ($shouldTrackTree && $token->isValue() && !$this->tree->inObject()) {
148 126
            $this->tree->traverseArray($this->pointer->referenceTokens());
149
        }
150
151 126
        if ($this->tree->changed && $this->pointers->count() > 1) {
152 28
            $this->pointer = $this->pointers->matchTree($this->tree);
153
        }
154
155 126
        $shouldBuffer = $this->tree->depth() >= 0
156 126
            && $this->pointer->matchesTree($this->tree)
157 126
            && ((!$this->expectsKey && $token->isValue()) || $this->treeIsDeep());
158
159 126
        if ($shouldBuffer) {
160 92
            $this->buffer .= $token;
161 92
            $this->pointers->markAsFound($this->pointer);
162
        }
163
164 126
        $token->mutateState($this);
165
    }
166
167
    /**
168
     * Determine whether the buffer contains tokens
169
     *
170
     * @return bool
171
     */
172 124
    public function hasBuffer(): bool
173
    {
174 124
        return $this->buffer != '';
175
    }
176
177
    /**
178
     * Retrieve the value from the buffer and reset it
179
     *
180
     * @return string
181
     */
182 92
    public function value(): string
183
    {
184 92
        $buffer = $this->buffer;
185
186 92
        $this->buffer = '';
187
188 92
        return $buffer;
189
    }
190
}
191