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

isString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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