1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.JSONParser = void 0;
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const C = {};
|
12 |
|
13 | const LEFT_BRACE = C.LEFT_BRACE = 0x1;
|
14 | const RIGHT_BRACE = C.RIGHT_BRACE = 0x2;
|
15 | const LEFT_BRACKET = C.LEFT_BRACKET = 0x3;
|
16 | const RIGHT_BRACKET = C.RIGHT_BRACKET = 0x4;
|
17 | const COLON = C.COLON = 0x5;
|
18 | const COMMA = C.COMMA = 0x6;
|
19 | const TRUE = C.TRUE = 0x7;
|
20 | const FALSE = C.FALSE = 0x8;
|
21 | const NULL = C.NULL = 0x9;
|
22 | const STRING = C.STRING = 0xa;
|
23 | const NUMBER = C.NUMBER = 0xb;
|
24 |
|
25 | const START = C.START = 0x11;
|
26 | const STOP = C.STOP = 0x12;
|
27 | const TRUE1 = C.TRUE1 = 0x21;
|
28 | const TRUE2 = C.TRUE2 = 0x22;
|
29 | const TRUE3 = C.TRUE3 = 0x23;
|
30 | const FALSE1 = C.FALSE1 = 0x31;
|
31 | const FALSE2 = C.FALSE2 = 0x32;
|
32 | const FALSE3 = C.FALSE3 = 0x33;
|
33 | const FALSE4 = C.FALSE4 = 0x34;
|
34 | const NULL1 = C.NULL1 = 0x41;
|
35 | const NULL2 = C.NULL2 = 0x42;
|
36 | const NULL3 = C.NULL3 = 0x43;
|
37 | const NUMBER1 = C.NUMBER1 = 0x51;
|
38 | const NUMBER3 = C.NUMBER3 = 0x53;
|
39 | const STRING1 = C.STRING1 = 0x61;
|
40 | const STRING2 = C.STRING2 = 0x62;
|
41 | const STRING3 = C.STRING3 = 0x63;
|
42 | const STRING4 = C.STRING4 = 0x64;
|
43 | const STRING5 = C.STRING5 = 0x65;
|
44 | const STRING6 = C.STRING6 = 0x66;
|
45 |
|
46 | const VALUE = C.VALUE = 0x71;
|
47 | const KEY = C.KEY = 0x72;
|
48 |
|
49 | const OBJECT = C.OBJECT = 0x81;
|
50 | const ARRAY = C.ARRAY = 0x82;
|
51 |
|
52 | const BACK_SLASH = "\\".charCodeAt(0);
|
53 | const FORWARD_SLASH = "\/".charCodeAt(0);
|
54 | const BACKSPACE = "\b".charCodeAt(0);
|
55 | const FORM_FEED = "\f".charCodeAt(0);
|
56 | const NEWLINE = "\n".charCodeAt(0);
|
57 | const CARRIAGE_RETURN = "\r".charCodeAt(0);
|
58 | const TAB = "\t".charCodeAt(0);
|
59 | const STRING_BUFFER_SIZE = 64 * 1024;
|
60 | function alloc(size) {
|
61 | return new Uint8Array(size);
|
62 | }
|
63 | class Parser {
|
64 | constructor() {
|
65 | this.tState = START;
|
66 | this.value = undefined;
|
67 | this.string = undefined;
|
68 | this.stringBuffer = alloc(STRING_BUFFER_SIZE);
|
69 | this.stringBufferOffset = 0;
|
70 | this.unicode = undefined;
|
71 | this.highSurrogate = undefined;
|
72 | this.key = undefined;
|
73 | this.mode = undefined;
|
74 | this.stack = [];
|
75 | this.state = VALUE;
|
76 | this.bytes_remaining = 0;
|
77 | this.bytes_in_sequence = 0;
|
78 | this.temp_buffs = { "2": alloc(2), "3": alloc(3), "4": alloc(4) };
|
79 | this.encoder = new TextEncoder();
|
80 | this.decoder = new TextDecoder();
|
81 |
|
82 | this.offset = -1;
|
83 | }
|
84 |
|
85 | static toknam(code) {
|
86 | const keys = Object.keys(C);
|
87 | for (let i = 0, l = keys.length; i < l; i++) {
|
88 | const key = keys[i];
|
89 | if (C[key] === code) {
|
90 | return key;
|
91 | }
|
92 | }
|
93 | return code && ("0x" + code.toString(16));
|
94 | }
|
95 | encode(string) { return this.encoder.encode(string); }
|
96 | decode(buffer) { return this.decoder.decode(buffer); }
|
97 | onError(err) { throw err; }
|
98 | charError(buffer, i) {
|
99 | this.tState = STOP;
|
100 | this.onError(new Error("Unexpected " + JSON.stringify(String.fromCharCode(buffer[i])) + " at position " + i + " in state " + Parser.toknam(this.tState)));
|
101 | }
|
102 | appendStringChar(char) {
|
103 | if (this.stringBufferOffset >= STRING_BUFFER_SIZE) {
|
104 | this.string += this.decode(this.stringBuffer);
|
105 | this.stringBufferOffset = 0;
|
106 | }
|
107 | this.stringBuffer[this.stringBufferOffset++] = char;
|
108 | }
|
109 | appendStringBuf(buf, start, end) {
|
110 | let size = buf.length;
|
111 | if (typeof start === 'number') {
|
112 | if (typeof end === 'number') {
|
113 | if (end < 0) {
|
114 |
|
115 | size = buf.length - start + end;
|
116 | }
|
117 | else {
|
118 | size = end - start;
|
119 | }
|
120 | }
|
121 | else {
|
122 | size = buf.length - start;
|
123 | }
|
124 | }
|
125 | if (size < 0) {
|
126 | size = 0;
|
127 | }
|
128 | if (this.stringBufferOffset + size > STRING_BUFFER_SIZE) {
|
129 | this.string += this.decode(this.stringBuffer.subarray(0, this.stringBufferOffset));
|
130 | this.stringBufferOffset = 0;
|
131 | }
|
132 | this.stringBuffer.set(buf.subarray(start, end), this.stringBufferOffset);
|
133 | this.stringBufferOffset += size;
|
134 | }
|
135 | write(buffer) {
|
136 | if (typeof buffer === "string")
|
137 | buffer = this.encode(buffer);
|
138 | let n;
|
139 | for (let i = 0, l = buffer.length; i < l; i++) {
|
140 | if (this.tState === START) {
|
141 | n = buffer[i];
|
142 | this.offset++;
|
143 | if (n === 0x7b) {
|
144 | this.onToken(LEFT_BRACE, "{");
|
145 | }
|
146 | else if (n === 0x7d) {
|
147 | this.onToken(RIGHT_BRACE, "}");
|
148 | }
|
149 | else if (n === 0x5b) {
|
150 | this.onToken(LEFT_BRACKET, "[");
|
151 | }
|
152 | else if (n === 0x5d) {
|
153 | this.onToken(RIGHT_BRACKET, "]");
|
154 | }
|
155 | else if (n === 0x3a) {
|
156 | this.onToken(COLON, ":");
|
157 | }
|
158 | else if (n === 0x2c) {
|
159 | this.onToken(COMMA, ",");
|
160 | }
|
161 | else if (n === 0x74) {
|
162 | this.tState = TRUE1;
|
163 | }
|
164 | else if (n === 0x66) {
|
165 | this.tState = FALSE1;
|
166 | }
|
167 | else if (n === 0x6e) {
|
168 | this.tState = NULL1;
|
169 | }
|
170 | else if (n === 0x22) {
|
171 | this.string = "";
|
172 | this.stringBufferOffset = 0;
|
173 | this.tState = STRING1;
|
174 | }
|
175 | else if (n === 0x2d) {
|
176 | this.string = "-";
|
177 | this.tState = NUMBER1;
|
178 | }
|
179 | else {
|
180 | if (n >= 0x30 && n < 0x40) {
|
181 | this.string = String.fromCharCode(n);
|
182 | this.tState = NUMBER3;
|
183 | }
|
184 | else if (n === 0x20 || n === 0x09 || n === 0x0a || n === 0x0d) {
|
185 |
|
186 | }
|
187 | else {
|
188 | return this.charError(buffer, i);
|
189 | }
|
190 | }
|
191 | }
|
192 | else if (this.tState === STRING1) {
|
193 | n = buffer[i];
|
194 |
|
195 |
|
196 | if (this.bytes_remaining > 0) {
|
197 | let j;
|
198 | for (j = 0; j < this.bytes_remaining; j++) {
|
199 | this.temp_buffs[this.bytes_in_sequence][this.bytes_in_sequence - this.bytes_remaining + j] = buffer[j];
|
200 | }
|
201 | this.appendStringBuf(this.temp_buffs[this.bytes_in_sequence]);
|
202 | this.bytes_in_sequence = this.bytes_remaining = 0;
|
203 | i = i + j - 1;
|
204 | }
|
205 | else if (this.bytes_remaining === 0 && n >= 128) {
|
206 | if (n <= 193 || n > 244) {
|
207 | return this.onError(new Error("Invalid UTF-8 character at position " + i + " in state " + Parser.toknam(this.tState)));
|
208 | }
|
209 | if ((n >= 194) && (n <= 223))
|
210 | this.bytes_in_sequence = 2;
|
211 | if ((n >= 224) && (n <= 239))
|
212 | this.bytes_in_sequence = 3;
|
213 | if ((n >= 240) && (n <= 244))
|
214 | this.bytes_in_sequence = 4;
|
215 | if ((this.bytes_in_sequence + i) > buffer.length) {
|
216 | for (let k = 0; k <= (buffer.length - 1 - i); k++) {
|
217 | this.temp_buffs[this.bytes_in_sequence][k] = buffer[i + k];
|
218 | }
|
219 | this.bytes_remaining = (i + this.bytes_in_sequence) - buffer.length;
|
220 | i = buffer.length - 1;
|
221 | }
|
222 | else {
|
223 | this.appendStringBuf(buffer, i, i + this.bytes_in_sequence);
|
224 | i = i + this.bytes_in_sequence - 1;
|
225 | }
|
226 | }
|
227 | else if (n === 0x22) {
|
228 | this.tState = START;
|
229 | this.string += this.decode(this.stringBuffer.subarray(0, this.stringBufferOffset));
|
230 | this.stringBufferOffset = 0;
|
231 | this.onToken(STRING, this.string);
|
232 | this.offset += this.encode(this.string).length + 1;
|
233 | this.string = undefined;
|
234 | }
|
235 | else if (n === 0x5c) {
|
236 | this.tState = STRING2;
|
237 | }
|
238 | else if (n >= 0x20) {
|
239 | this.appendStringChar(n);
|
240 | }
|
241 | else {
|
242 | return this.charError(buffer, i);
|
243 | }
|
244 | }
|
245 | else if (this.tState === STRING2) {
|
246 | n = buffer[i];
|
247 | if (n === 0x22) {
|
248 | this.appendStringChar(n);
|
249 | this.tState = STRING1;
|
250 | }
|
251 | else if (n === 0x5c) {
|
252 | this.appendStringChar(BACK_SLASH);
|
253 | this.tState = STRING1;
|
254 | }
|
255 | else if (n === 0x2f) {
|
256 | this.appendStringChar(FORWARD_SLASH);
|
257 | this.tState = STRING1;
|
258 | }
|
259 | else if (n === 0x62) {
|
260 | this.appendStringChar(BACKSPACE);
|
261 | this.tState = STRING1;
|
262 | }
|
263 | else if (n === 0x66) {
|
264 | this.appendStringChar(FORM_FEED);
|
265 | this.tState = STRING1;
|
266 | }
|
267 | else if (n === 0x6e) {
|
268 | this.appendStringChar(NEWLINE);
|
269 | this.tState = STRING1;
|
270 | }
|
271 | else if (n === 0x72) {
|
272 | this.appendStringChar(CARRIAGE_RETURN);
|
273 | this.tState = STRING1;
|
274 | }
|
275 | else if (n === 0x74) {
|
276 | this.appendStringChar(TAB);
|
277 | this.tState = STRING1;
|
278 | }
|
279 | else if (n === 0x75) {
|
280 | this.unicode = "";
|
281 | this.tState = STRING3;
|
282 | }
|
283 | else {
|
284 | return this.charError(buffer, i);
|
285 | }
|
286 | }
|
287 | else if (this.tState === STRING3 || this.tState === STRING4 || this.tState === STRING5 || this.tState === STRING6) {
|
288 | n = buffer[i];
|
289 |
|
290 | if ((n >= 0x30 && n < 0x40) || (n > 0x40 && n <= 0x46) || (n > 0x60 && n <= 0x66)) {
|
291 | this.unicode += String.fromCharCode(n);
|
292 | if (this.tState++ === STRING6) {
|
293 | const intVal = parseInt(this.unicode, 16);
|
294 | this.unicode = undefined;
|
295 | if (this.highSurrogate !== undefined && intVal >= 0xDC00 && intVal < (0xDFFF + 1)) {
|
296 | this.appendStringBuf(this.encode(String.fromCharCode(this.highSurrogate, intVal)));
|
297 | this.highSurrogate = undefined;
|
298 | }
|
299 | else if (this.highSurrogate === undefined && intVal >= 0xD800 && intVal < (0xDBFF + 1)) {
|
300 | this.highSurrogate = intVal;
|
301 | }
|
302 | else {
|
303 | if (this.highSurrogate !== undefined) {
|
304 | this.appendStringBuf(this.encode(String.fromCharCode(this.highSurrogate)));
|
305 | this.highSurrogate = undefined;
|
306 | }
|
307 | this.appendStringBuf(this.encode(String.fromCharCode(intVal)));
|
308 | }
|
309 | this.tState = STRING1;
|
310 | }
|
311 | }
|
312 | else {
|
313 | return this.charError(buffer, i);
|
314 | }
|
315 | }
|
316 | else if (this.tState === NUMBER1 || this.tState === NUMBER3) {
|
317 | n = buffer[i];
|
318 | switch (n) {
|
319 | case 0x30:
|
320 | case 0x31:
|
321 | case 0x32:
|
322 | case 0x33:
|
323 | case 0x34:
|
324 | case 0x35:
|
325 | case 0x36:
|
326 | case 0x37:
|
327 | case 0x38:
|
328 | case 0x39:
|
329 | case 0x2e:
|
330 | case 0x65:
|
331 | case 0x45:
|
332 | case 0x2b:
|
333 | case 0x2d:
|
334 | this.string += String.fromCharCode(n);
|
335 | this.tState = NUMBER3;
|
336 | break;
|
337 | default:
|
338 | this.tState = START;
|
339 | const error = this.numberReviver(this.string);
|
340 | if (error) {
|
341 | return error;
|
342 | }
|
343 | this.offset += this.string.length - 1;
|
344 | this.string = undefined;
|
345 | i--;
|
346 | break;
|
347 | }
|
348 | }
|
349 | else if (this.tState === TRUE1) {
|
350 | if (buffer[i] === 0x72) {
|
351 | this.tState = TRUE2;
|
352 | }
|
353 | else {
|
354 | return this.charError(buffer, i);
|
355 | }
|
356 | }
|
357 | else if (this.tState === TRUE2) {
|
358 | if (buffer[i] === 0x75) {
|
359 | this.tState = TRUE3;
|
360 | }
|
361 | else {
|
362 | return this.charError(buffer, i);
|
363 | }
|
364 | }
|
365 | else if (this.tState === TRUE3) {
|
366 | if (buffer[i] === 0x65) {
|
367 | this.tState = START;
|
368 | this.onToken(TRUE, true);
|
369 | this.offset += 3;
|
370 | }
|
371 | else {
|
372 | return this.charError(buffer, i);
|
373 | }
|
374 | }
|
375 | else if (this.tState === FALSE1) {
|
376 | if (buffer[i] === 0x61) {
|
377 | this.tState = FALSE2;
|
378 | }
|
379 | else {
|
380 | return this.charError(buffer, i);
|
381 | }
|
382 | }
|
383 | else if (this.tState === FALSE2) {
|
384 | if (buffer[i] === 0x6c) {
|
385 | this.tState = FALSE3;
|
386 | }
|
387 | else {
|
388 | return this.charError(buffer, i);
|
389 | }
|
390 | }
|
391 | else if (this.tState === FALSE3) {
|
392 | if (buffer[i] === 0x73) {
|
393 | this.tState = FALSE4;
|
394 | }
|
395 | else {
|
396 | return this.charError(buffer, i);
|
397 | }
|
398 | }
|
399 | else if (this.tState === FALSE4) {
|
400 | if (buffer[i] === 0x65) {
|
401 | this.tState = START;
|
402 | this.onToken(FALSE, false);
|
403 | this.offset += 4;
|
404 | }
|
405 | else {
|
406 | return this.charError(buffer, i);
|
407 | }
|
408 | }
|
409 | else if (this.tState === NULL1) {
|
410 | if (buffer[i] === 0x75) {
|
411 | this.tState = NULL2;
|
412 | }
|
413 | else {
|
414 | return this.charError(buffer, i);
|
415 | }
|
416 | }
|
417 | else if (this.tState === NULL2) {
|
418 | if (buffer[i] === 0x6c) {
|
419 | this.tState = NULL3;
|
420 | }
|
421 | else {
|
422 | return this.charError(buffer, i);
|
423 | }
|
424 | }
|
425 | else if (this.tState === NULL3) {
|
426 | if (buffer[i] === 0x6c) {
|
427 | this.tState = START;
|
428 | this.onToken(NULL, null);
|
429 | this.offset += 3;
|
430 | }
|
431 | else {
|
432 | return this.charError(buffer, i);
|
433 | }
|
434 | }
|
435 | }
|
436 | }
|
437 | parseError(token, value) {
|
438 | this.tState = STOP;
|
439 | this.onError(new Error("Unexpected " + Parser.toknam(token) + (value ? ("(" + JSON.stringify(value) + ")") : "") + " in state " + Parser.toknam(this.state)));
|
440 | }
|
441 | push() {
|
442 | this.stack.push({ value: this.value, key: this.key, mode: this.mode });
|
443 | }
|
444 | pop() {
|
445 | const value = this.value;
|
446 | const parent = this.stack.pop();
|
447 | this.value = parent.value;
|
448 | this.key = parent.key;
|
449 | this.mode = parent.mode;
|
450 | this.emit(value);
|
451 | if (!this.mode) {
|
452 | this.state = VALUE;
|
453 | }
|
454 | }
|
455 | emit(value) {
|
456 | if (this.mode) {
|
457 | this.state = COMMA;
|
458 | }
|
459 | this.onValue(value);
|
460 | }
|
461 | onValue(value) {
|
462 |
|
463 | }
|
464 | onToken(token, value) {
|
465 | if (this.state === VALUE) {
|
466 | if (token === STRING || token === NUMBER || token === TRUE || token === FALSE || token === NULL) {
|
467 | if (this.value) {
|
468 | this.value[this.key] = value;
|
469 | }
|
470 | this.emit(value);
|
471 | }
|
472 | else if (token === LEFT_BRACE) {
|
473 | this.push();
|
474 | if (this.value) {
|
475 | this.value = this.value[this.key] = {};
|
476 | }
|
477 | else {
|
478 | this.value = {};
|
479 | }
|
480 | this.key = undefined;
|
481 | this.state = KEY;
|
482 | this.mode = OBJECT;
|
483 | }
|
484 | else if (token === LEFT_BRACKET) {
|
485 | this.push();
|
486 | if (this.value) {
|
487 | this.value = this.value[this.key] = [];
|
488 | }
|
489 | else {
|
490 | this.value = [];
|
491 | }
|
492 | this.key = 0;
|
493 | this.mode = ARRAY;
|
494 | this.state = VALUE;
|
495 | }
|
496 | else if (token === RIGHT_BRACE) {
|
497 | if (this.mode === OBJECT) {
|
498 | this.pop();
|
499 | }
|
500 | else {
|
501 | return this.parseError(token, value);
|
502 | }
|
503 | }
|
504 | else if (token === RIGHT_BRACKET) {
|
505 | if (this.mode === ARRAY) {
|
506 | this.pop();
|
507 | }
|
508 | else {
|
509 | return this.parseError(token, value);
|
510 | }
|
511 | }
|
512 | else {
|
513 | return this.parseError(token, value);
|
514 | }
|
515 | }
|
516 | else if (this.state === KEY) {
|
517 | if (token === STRING) {
|
518 | this.key = value;
|
519 | this.state = COLON;
|
520 | }
|
521 | else if (token === RIGHT_BRACE) {
|
522 | this.pop();
|
523 | }
|
524 | else {
|
525 | return this.parseError(token, value);
|
526 | }
|
527 | }
|
528 | else if (this.state === COLON) {
|
529 | if (token === COLON) {
|
530 | this.state = VALUE;
|
531 | }
|
532 | else {
|
533 | return this.parseError(token, value);
|
534 | }
|
535 | }
|
536 | else if (this.state === COMMA) {
|
537 | if (token === COMMA) {
|
538 | if (this.mode === ARRAY) {
|
539 | this.key++;
|
540 | this.state = VALUE;
|
541 | }
|
542 | else if (this.mode === OBJECT) {
|
543 | this.state = KEY;
|
544 | }
|
545 | }
|
546 | else if (token === RIGHT_BRACKET && this.mode === ARRAY || token === RIGHT_BRACE && this.mode === OBJECT) {
|
547 | this.pop();
|
548 | }
|
549 | else {
|
550 | return this.parseError(token, value);
|
551 | }
|
552 | }
|
553 | else {
|
554 | return this.parseError(token, value);
|
555 | }
|
556 | }
|
557 |
|
558 |
|
559 | numberReviver(text) {
|
560 | const result = Number(text);
|
561 | if (isNaN(result)) {
|
562 | return this.charError(buffer, i);
|
563 | }
|
564 | if ((text.match(/[0-9]+/) == text) && (result.toString() != text)) {
|
565 |
|
566 | this.onToken(STRING, text);
|
567 | }
|
568 | else {
|
569 | this.onToken(NUMBER, result);
|
570 | }
|
571 | }
|
572 | }
|
573 | exports.JSONParser = Parser;
|
574 | Parser.C = C;
|
575 | exports.default = Parser;
|
576 |
|
\ | No newline at end of file |