Passed
Push — master ( da4da2...955b82 )
by Nate
04:34
created

JsonElementReader::push()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 11
Ratio 100 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 11
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 2
crap 2
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
declare(strict_types=1);
8
namespace Tebru\Gson\Internal;
9
10
use ArrayIterator;
11
use Iterator;
12
use Tebru\Gson\Element\JsonArray;
13
use Tebru\Gson\Element\JsonElement;
14
use Tebru\Gson\Element\JsonNull;
15
use Tebru\Gson\Element\JsonObject;
16
use Tebru\Gson\Element\JsonPrimitive;
17
use Tebru\Gson\JsonReadable;
18
use Tebru\Gson\JsonToken;
19
20
/**
21
 * Class JsonElementReader
22
 *
23
 * @author Nate Brunette <[email protected]>
24
 */
25
final class JsonElementReader extends JsonReader implements JsonReadable
26
{
27
    /**
28
     * Constructor
29
     *
30
     * @param JsonElement $jsonElement
31
     */
32 69
    public function __construct(JsonElement $jsonElement)
33
    {
34 69
        $this->push($jsonElement);
35 69
    }
36
37
    /**
38
     * Consumes the next token and asserts it's the beginning of a new array
39
     *
40
     * @return void
41
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BEGIN_ARRAY
42
     */
43 15 View Code Duplication
    public function beginArray(): void
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
    {
45 15
        $this->expect(JsonToken::BEGIN_ARRAY);
46
47
        /** @var JsonArray $jsonArray */
48 14
        $jsonArray = $this->pop();
49 14
        $this->push($jsonArray->getIterator(), ArrayIterator::class);
50 14
        $this->pathIndices[$this->stackSize - 1] = 0;
51 14
    }
52
53
    /**
54
     * Consumes the next token and asserts it's the beginning of a new object
55
     *
56
     * @return void
57
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BEGIN_OBJECT
58
     */
59 17
    public function beginObject(): void
60
    {
61 17
        $this->expect(JsonToken::BEGIN_OBJECT);
62
63
        /** @var JsonObject $jsonObject */
64 16
        $jsonObject = $this->pop();
65
66 16
        $this->push(new JsonObjectIterator($jsonObject), JsonObjectIterator::class);
67 16
    }
68
69
    /**
70
     * Consumes the value of the next token, asserts it's a boolean and returns it
71
     *
72
     * @return bool
73
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BOOLEAN
74
     */
75 6
    public function nextBoolean(): bool
76
    {
77 6
        $this->expect(JsonToken::BOOLEAN);
78
79
        /** @var JsonPrimitive $primitive */
80 5
        $primitive = $this->pop();
81
82 5
        $this->incrementPathIndex();
83
84 5
        return $primitive->asBoolean();
85
    }
86
87
    /**
88
     * Consumes the value of the next token, asserts it's a double and returns it
89
     *
90
     * @return double
91
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NUMBER
92
     */
93 3
    public function nextDouble(): float
94
    {
95 3
        $this->expect(JsonToken::NUMBER);
96
97
        /** @var JsonPrimitive $primitive */
98 2
        $primitive = $this->pop();
99
100 2
        $this->incrementPathIndex();
101
102 2
        return $primitive->asFloat();
103
    }
104
105
    /**
106
     * Consumes the value of the next token, asserts it's an int and returns it
107
     *
108
     * @return int
109
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NUMBER
110
     */
111 6
    public function nextInteger(): int
112
    {
113 6
        $this->expect(JsonToken::NUMBER);
114
115
        /** @var JsonPrimitive $primitive */
116 5
        $primitive = $this->pop();
117
118 5
        $this->incrementPathIndex();
119
120 5
        return $primitive->asInteger();
121
    }
122
123
    /**
124
     * Consumes the value of the next token, asserts it's a string and returns it
125
     *
126
     * @return string
127
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NAME or STRING
128
     */
129 14 View Code Duplication
    public function nextString(): string
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
130
    {
131 14
        $peek = $this->peek();
132 14
        if ($peek === JsonToken::NAME) {
133 1
            return $this->nextName();
134
        }
135
136 13
        $this->expect(JsonToken::STRING);
137
138
        /** @var JsonPrimitive $primitive */
139 12
        $primitive = $this->pop();
140
141 12
        $this->incrementPathIndex();
142
143 12
        return $primitive->asString();
144
    }
145
146
    /**
147
     * Returns an enum representing the type of the next token without consuming it
148
     *
149
     * @return string
150
     */
151 69
    public function peek(): string
152
    {
153 69
        if (null !== $this->currentToken) {
154 23
            return $this->currentToken;
155
        }
156
157 69
        if (0 === $this->stackSize) {
158 1
            $this->currentToken = JsonToken::END_DOCUMENT;
159
160 1
            return $this->currentToken;
161
        }
162
163 69
        $token = null;
164 69
        $element = $this->stack[$this->stackSize - 1];
165
166 69
        switch ($this->stackTypes[$this->stackSize - 1]) {
167 69
            case JsonArray::class:
168 16
                $token = JsonToken::BEGIN_ARRAY;
169 16
                break;
170 66
            case JsonNull::class:
171 2
                $token = JsonToken::NULL;
172 2
                break;
173 64
            case JsonObject::class:
174 20
                $token = JsonToken::BEGIN_OBJECT;
175 20
                break;
176 61
            case JsonPrimitive::class:
177
                /** @var JsonPrimitive $element */
178 45
                if ($element->isString()) {
179 18
                    $token = JsonToken::STRING;
180 28
                } elseif ($element->isBoolean()) {
181 8
                    $token = JsonToken::BOOLEAN;
182 21
                } elseif ($element->isNumber()) {
183 21
                    $token = JsonToken::NUMBER;
184
                }
185
186 45
                break;
187 27
            case JsonObjectIterator::class:
188
                /** @var JsonObjectIterator $element */
189 15
                $token = $element->valid() ? JsonToken::NAME : JsonToken::END_OBJECT;
190
191 15
                break;
192 13 View Code Duplication
            case ArrayIterator::class:
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
                /** @var ArrayIterator $element */
194 13
                if ($element->valid()) {
195 9
                    $this->push($element->current());
196 9
                    $element->next();
197
198 9
                    $token = $this->peek();
199
                } else {
200 7
                    $token = JsonToken::END_ARRAY;
201
                }
202
203 13
                break;
204
        }
205
206 69
        $this->currentToken = $token;
207
208 69
        return $this->currentToken;
209
    }
210
211
    /**
212
     * Get the current read path in json xpath format
213
     *
214
     * @return string
215
     */
216 10 View Code Duplication
    public function getPath(): string
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
217
    {
218 10
        $result = '$';
219 10
        foreach ($this->stack as $index => $item) {
220 10
            if ($item instanceof ArrayIterator && isset($this->pathIndices[$index])) {
221 1
                $result .= '['.$this->pathIndices[$index].']';
222
            }
223
224 10
            if ($item instanceof JsonObjectIterator && isset($this->pathNames[$index])) {
225 10
                $result .= '.'.$this->pathNames[$index];
226
            }
227
        }
228
229 10
        return $result;
230
    }
231
232
    /**
233
     * Push an element onto the stack
234
     *
235
     * @param JsonElement|Iterator $element
236
     * @param string $type
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
237
     */
238 69 View Code Duplication
    protected function push($element, $type = null): void
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
239
    {
240 69
        if (null === $type) {
241 69
            $type = get_class($element);
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $type. This often makes code more readable.
Loading history...
242
        }
243
244 69
        $this->stack[$this->stackSize] = $element;
245 69
        $this->stackTypes[$this->stackSize] = $type;
246 69
        $this->stackSize++;
247 69
        $this->currentToken = null;
248 69
    }
249
}
250