Passed
Pull Request — master (#184)
by Christoffer
02:26
created

isSpread()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 3
nc 3
nop 3
1
<?php
2
3
namespace Digia\GraphQL\Language;
4
5
/**
6
 * @param int $code
7
 * @return string
8
 */
9
function chrUTF8(int $code)
10
{
11
    if ($code <= 255) {
12
        return \chr($code);
13
    }
14
15
    return \mb_convert_encoding(\pack('N', $code), 'UTF-8', 'UCS-4BE');
16
}
17
18
/**
19
 * @param string $string
20
 * @param string $encoding
21
 * @return int
22
 */
23
function ordUTF8(string $string)
24
{
25
    if (!$string && '0' !== $string) {
26
        return 0;
27
    }
28
29
    if (!isset($string[1])) {
30
        return \ord($string);
31
    }
32
33
    return \unpack('N', \mb_convert_encoding($string, 'UCS-4BE', 'UTF-8'))[1];
34
}
35
36
/**
37
 * @param string $string
38
 * @param int    $position
39
 * @return int
40
 */
41
function charCodeAt(string $string, int $position): int
42
{
43
    return ordUTF8(\mb_substr($string, $position, 1, 'UTF-8'));
44
}
45
46
/**
47
 * @param int $code
48
 * @return string
49
 */
50
function printCharCode(int $code): string
51
{
52
    if ($code === 0x0000) {
53
        return '<EOF>';
54
    }
55
56
    return $code < 0x007F
57
        // Trust JSON for ASCII.
58
        ? \json_encode($code < 255 ? \chr($code) : chrUTF8($code))
59
        // Otherwise print the escaped form.
60
        : '"\\u' . \dechex($code) . '"';
61
}
62
63
/**
64
 * @param string   $string
65
 * @param int      $start
66
 * @param int|null $end
67
 * @return string
68
 */
69
function sliceString(string $string, int $start, int $end = null): string
70
{
71
    $length = $end !== null ? $end - $start : \mb_strlen($string) - $start;
72
    return \mb_substr($string, $start, $length);
73
}
74
75
/**
76
 * @param int $code
77
 * @return bool
78
 */
79
function isLetter(int $code): bool
80
{
81
    return ($code >= 65 && $code <= 90) || ($code >= 97 && $code <= 122); // a-z or A-Z
82
}
83
84
/**
85
 * @param int $code
86
 * @return bool
87
 */
88
function isNumber(int $code): bool
89
{
90
    return $code >= 48 && $code <= 57; // 0-9
91
}
92
93
/**
94
 * @param int $code
95
 * @return bool
96
 */
97
function isUnderscore(int $code): bool
98
{
99
    return $code === 95; // _
100
}
101
102
/**
103
 * @param int $code
104
 * @return bool
105
 */
106
function isAlphaNumeric(int $code): bool
107
{
108
    return isLetter($code) || isNumber($code) || isUnderscore($code);
109
}
110
111
/**
112
 * @param int $code
113
 * @return bool
114
 */
115
function isLineTerminator(int $code): bool
116
{
117
    return $code === 0x000a || $code === 0x000d;
118
}
119
120
/**
121
 * @param int $code
122
 * @return bool
123
 */
124
function isSourceCharacter(int $code): bool
125
{
126
    return $code < 0x0020 && $code !== 0x0009; // any source character EXCEPT HT (Horizontal Tab)
127
}
128
129
/**
130
 * @param string $body
131
 * @param int    $code
132
 * @param int    $pos
133
 * @return bool
134
 */
135
function isSpread(string $body, int $code, int $pos): bool
136
{
137
    return $code === 46 &&
138
        charCodeAt($body, $pos + 1) === 46 &&
139
        charCodeAt($body, $pos + 2) === 46; // ...
140
}
141
142
/**
143
 * @param string $body
144
 * @param int    $code
145
 * @param int    $pos
146
 * @return bool
147
 */
148
function isString(string $body, int $code, int $pos): bool
149
{
150
    return $code === 34 && charCodeAt($body, $pos + 1) !== 34;
151
}
152
153
/**
154
 * @param string $body
155
 * @param int    $code
156
 * @param int    $pos
157
 * @return bool
158
 */
159
function isTripleQuote(string $body, int $code, int $pos): bool
160
{
161
    return $code === 34 &&
162
        charCodeAt($body, $pos + 1) === 34 &&
163
        charCodeAt($body, $pos + 2) === 34; // """
164
}
165
166
/**
167
 * @param string $body
168
 * @param int    $code
169
 * @param int    $pos
170
 * @return bool
171
 */
172
function isEscapedTripleQuote(
173
    string $body,
174
    int $code,
175
    int $pos
176
): bool {
177
    return $code === 92 &&
178
        charCodeAt($body, $pos + 1) === 34 &&
179
        charCodeAt($body, $pos + 2) === 34 &&
180
        charCodeAt($body, $pos + 3) === 34;
181
}
182
183
/**
184
 * Converts four hexidecimal chars to the integer that the
185
 * string represents. For example, uniCharCode('0','0','0','f')
186
 * will return 15, and uniCharCode('0','0','f','f') returns 255.
187
 *
188
 * @param string $a
189
 * @param string $b
190
 * @param string $c
191
 * @param string $d
192
 * @return string
193
 */
194
function uniCharCode(string $a, string $b, string $c, string $d): string
195
{
196
    return (\dechex(ordUTF8($a)) << 12) |
197
        (\dechex(ordUTF8($b)) << 8) |
198
        (\dechex(ordUTF8($c)) << 4) |
199
        \dechex(ordUTF8($d));
200
}
201
202
/**
203
 * @param string $value
204
 * @return bool
205
 */
206
function isOperation(string $value): bool
207
{
208
    // TODO: Benchmark
209
    return \in_array($value, ['query', 'mutation', 'subscription'], true);
210
}
211
212
/**
213
 * @param array $location
214
 * @return array|null
215
 */
216
function locationShorthandToArray(array $location): ?array
217
{
218
    return isset($location[0], $location[1]) ? ['line' => $location[0], 'column' => $location[1]] : null;
219
}
220
221
/**
222
 * @param array $locations
223
 * @return array
224
 */
225
function locationsShorthandToArray(array $locations): array
226
{
227
    return array_map(function ($shorthand) {
228
        return locationShorthandToArray($shorthand);
229
    }, $locations);
230
}
231
232
/**
233
 * @param array $array
234
 * @return string
235
 */
236
function block(array $array): string
237
{
238
    return !empty($array) ? "{\n" . indent(implode("\n", $array)) . "\n}" : '';
239
}
240
241
/**
242
 * @param string      $start
243
 * @param null|string $maybeString
244
 * @param null|string $end
245
 * @return string
246
 */
247
function wrap(string $start, ?string $maybeString = null, ?string $end = null): string
248
{
249
    return null !== $maybeString ? ($start . $maybeString . ($end ?? '')) : '';
250
}
251
252
/**
253
 * @param null|string $maybeString
254
 * @return string
255
 */
256
function indent(?string $maybeString): string
257
{
258
    return null !== $maybeString ? '  ' . preg_replace("/\n/", "\n  ", $maybeString) : '';
259
}
260
261
/**
262
 * @param string $str
263
 * @return string
264
 */
265
function dedent(string $str): string
266
{
267
    $trimmed = \preg_replace("/^\n*|[ \t]*$/", '', $str); // Remove leading newline and trailing whitespace
268
    $matches = [];
269
    \preg_match("/^[ \t]*/", $trimmed, $matches); // Figure out indent
270
    $indent = $matches[0];
271
    return \str_replace($indent, '', $trimmed); // Remove indent
272
}
273