1 package net.minidev.json.parser;
2
3
18 import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_CHAR;
19 import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF;
20 import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_LEADING_0;
21 import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_TOKEN;
22 import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_UNICODE;
23
24 import java.io.IOException;
25 import java.math.BigDecimal;
26 import java.math.BigInteger;
27
28 import net.minidev.json.writer.JsonReader;
29 import net.minidev.json.writer.JsonReaderI;
30
31
40 abstract class JSONParserBase {
41 protected char c;
42 JsonReader base;
43 public final static byte EOI = 0x1A;
44 protected static final char MAX_STOP = 126;
45 private String lastKey;
46
47 protected static boolean[] stopAll = new boolean[MAX_STOP];
48 protected static boolean[] stopArray = new boolean[MAX_STOP];
49 protected static boolean[] stopKey = new boolean[MAX_STOP];
50 protected static boolean[] stopValue = new boolean[MAX_STOP];
51 protected static boolean[] stopX = new boolean[MAX_STOP];
52
53 static {
54 stopKey[':'] = stopKey[EOI] = true;
55 stopValue[','] = stopValue['}'] = stopValue[EOI] = true;
56 stopArray[','] = stopArray[']'] = stopArray[EOI] = true;
57 stopX[EOI] = true;
58 stopAll[','] = stopAll[':'] = true;
59 stopAll[']'] = stopAll['}'] = stopAll[EOI] = true;
60 }
61
62
65
66
67 protected final MSB sb = new MSB(15);
68 protected Object xo;
69 protected String xs;
70 protected int pos;
71
72
75 protected final boolean acceptLeadinZero;
76 protected final boolean acceptNaN;
77 protected final boolean acceptNonQuote;
78 protected final boolean acceptSimpleQuote;
79 protected final boolean acceptUselessComma;
80 protected final boolean checkTaillingData;
81 protected final boolean checkTaillingSpace;
82 protected final boolean ignoreControlChar;
83 protected final boolean useHiPrecisionFloat;
84 protected final boolean useIntegerStorage;
85 protected final boolean reject127;
86
87 public JSONParserBase(int permissiveMode) {
88 this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0;
89 this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0;
90 this.acceptSimpleQuote = (permissiveMode & JSONParser.ACCEPT_SIMPLE_QUOTE) > 0;
91 this.ignoreControlChar = (permissiveMode & JSONParser.IGNORE_CONTROL_CHAR) > 0;
92 this.useIntegerStorage = (permissiveMode & JSONParser.USE_INTEGER_STORAGE) > 0;
93 this.acceptLeadinZero = (permissiveMode & JSONParser.ACCEPT_LEADING_ZERO) > 0;
94 this.acceptUselessComma = (permissiveMode & JSONParser.ACCEPT_USELESS_COMMA) > 0;
95 this.useHiPrecisionFloat = (permissiveMode & JSONParser.USE_HI_PRECISION_FLOAT) > 0;
96 this.checkTaillingData = (permissiveMode & (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE)) != (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE);
97 this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0;
98 this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0;
99 }
100
101 public void checkControleChar() throws ParseException {
102 if (ignoreControlChar)
103 return;
104 int l = xs.length();
105 for (int i = 0; i < l; i++) {
106 char c = xs.charAt(i);
107 if (c < 0)
108 continue;
109 if (c <= 31)
110 throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c);
111 if (c == 127) {
112 if (reject127)
113 throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c);
114 }
115 }
116 }
117
118 public void checkLeadinZero() throws ParseException {
119 int len = xs.length();
120 if (len == 1)
121 return;
122 if (len == 2) {
123 if (xs.equals("00"))
124 throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
125 return;
126 }
127 char c1 = xs.charAt(0);
128 char c2 = xs.charAt(1);
129 if (c1 == '-') {
130 char c3 = xs.charAt(2);
131 if (c2 == '0' && c3 >= '0' && c3 <= '9')
132 throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
133 return;
134 }
135 if (c1 == '0' && c2 >= '0' && c2 <= '9')
136 throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
137 }
138
139 protected Number extractFloat() throws ParseException {
140 if (!acceptLeadinZero)
141 checkLeadinZero();
142 if (!useHiPrecisionFloat)
143 return Float.parseFloat(xs);
144 if (xs.length() > 18)
145 return new BigDecimal(xs);
146 return Double.parseDouble(xs);
147 }
148
149
153 protected <T> T parse(JsonReaderI<T> mapper) throws ParseException {
154 this.pos = -1;
155 T result;
156 try {
157 read();
158 result = readFirst(mapper);
159 if (checkTaillingData) {
160 if (!checkTaillingSpace)
161 skipSpace();
162 if (c != EOI)
163 throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c);
164 }
165 } catch (IOException e) {
166 throw new ParseException(pos, e);
167 }
168 xs = null;
169 xo = null;
170 return result;
171 }
172
173 protected Number parseNumber(String s) throws ParseException {
174
175 int p = 0;
176
177 int l = s.length();
178
179 int max = 19;
180 boolean neg;
181
182 if (s.charAt(0) == '-') {
183 p++;
184 max++;
185 neg = true;
186 if (!acceptLeadinZero && l >= 3 && s.charAt(1) == '0')
187 throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
188 } else {
189 neg = false;
190 if (!acceptLeadinZero && l >= 2 && s.charAt(0) == '0')
191 throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
192 }
193
194 boolean mustCheck;
195 if (l < max) {
196 max = l;
197 mustCheck = false;
198 } else if (l > max) {
199 return new BigInteger(s, 10);
200 } else {
201 max = l - 1;
202 mustCheck = true;
203 }
204
205 long r = 0;
206 while (p < max) {
207 r = (r * 10L) + ('0' - s.charAt(p++));
208 }
209 if (mustCheck) {
210 boolean isBig;
211 if (r > -922337203685477580L) {
212 isBig = false;
213 } else if (r < -922337203685477580L) {
214 isBig = true;
215 } else {
216 if (neg)
217 isBig = (s.charAt(p) > '8');
218 else
219 isBig = (s.charAt(p) > '7');
220 }
221 if (isBig)
222 return new BigInteger(s, 10);
223 r = r * 10L + ('0' - s.charAt(p));
224 }
225 if (neg) {
226 if (this.useIntegerStorage && r >= Integer.MIN_VALUE)
227 return (int) r;
228 return r;
229 }
230 r = -r;
231 if (this.useIntegerStorage && r <= Integer.MAX_VALUE)
232 return (int) r;
233 return r;
234 }
235
236 abstract protected void read() throws IOException;
237
238 protected <T> T readArray(JsonReaderI<T> mapper) throws ParseException, IOException {
239 Object current = mapper.createArray();
240 if (c != '[')
241 throw new RuntimeException("Internal Error");
242 read();
243 boolean needData = false;
244
245 if (c == ',' && !acceptUselessComma)
246 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
247 for (;;) {
248 switch (c) {
249 case ' ':
250 case '\r':
251 case '\n':
252 case '\t':
253 read();
254 continue;
255 case ']':
256 if (needData && !acceptUselessComma)
257 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
258 read();
259
260 return mapper.convert(current);
261 case ':':
262 case '}':
263 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
264 case ',':
265 if (needData && !acceptUselessComma)
266 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
267 read();
268 needData = true;
269 continue;
270 case EOI:
271 throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF");
272 default:
273 mapper.addValue(current, readMain(mapper, stopArray));
274 needData = false;
275 continue;
276 }
277 }
278 }
279
280
284 protected <T> T readFirst(JsonReaderI<T> mapper) throws ParseException, IOException {
285 for (;;) {
286 switch (c) {
287
288 case ' ':
289 case '\r':
290 case '\n':
291 case '\t':
292 read();
293 continue;
294
295 case ':':
296 case '}':
297 case ']':
298 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
299
300 case '{':
301 return readObject(mapper);
302
303 case '[':
304 return readArray(mapper);
305
306 case '"':
307 case '\'':
308 readString();
309
310 return mapper.convert(xs);
311
312 case 'n':
313 readNQString(stopX);
314 if ("null".equals(xs)) {
315
316 return null;
317 }
318 if (!acceptNonQuote)
319 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
320
321 return mapper.convert(xs);
322
323 case 'f':
324 readNQString(stopX);
325 if ("false".equals(xs)) {
326
327 return mapper.convert(Boolean.FALSE);
328 }
329 if (!acceptNonQuote)
330 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
331
332 return mapper.convert(xs);
333
334 case 't':
335 readNQString(stopX);
336 if ("true".equals(xs)) {
337
338 return mapper.convert(Boolean.TRUE);
339 }
340 if (!acceptNonQuote)
341 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
342
343 return mapper.convert(xs);
344
345 case 'N':
346 readNQString(stopX);
347 if (!acceptNaN)
348 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
349 if ("NaN".equals(xs)) {
350
351 return mapper.convert(Float.valueOf(Float.NaN));
352 }
353 if (!acceptNonQuote)
354 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
355
356 return mapper.convert(xs);
357
358 case '0':
359 case '1':
360 case '2':
361 case '3':
362 case '4':
363 case '5':
364 case '6':
365 case '7':
366 case '8':
367 case '9':
368 case '-':
369 xo = readNumber(stopX);
370
371 return mapper.convert(xo);
372 default:
373 readNQString(stopX);
374 if (!acceptNonQuote)
375 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
376
377 return mapper.convert(xs);
378 }
379 }
380 }
381
382
386 protected Object readMain(JsonReaderI<?> mapper, boolean stop[]) throws ParseException, IOException {
387 for (;;) {
388 switch (c) {
389
390 case ' ':
391 case '\r':
392 case '\n':
393 case '\t':
394 read();
395 continue;
396
397 case ':':
398 case '}':
399 case ']':
400 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
401
402 case '{':
403 return readObject(mapper.startObject(lastKey));
404
405 case '[':
406 return readArray(mapper.startArray(lastKey));
407
408 case '"':
409 case '\'':
410 readString();
411
412 return xs;
413
414 case 'n':
415 readNQString(stop);
416 if ("null".equals(xs)) {
417
418 return null;
419 }
420 if (!acceptNonQuote)
421 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
422
423 return xs;
424
425 case 'f':
426 readNQString(stop);
427 if ("false".equals(xs)) {
428
429 return Boolean.FALSE;
430 }
431 if (!acceptNonQuote)
432 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
433
434 return xs;
435
436 case 't':
437 readNQString(stop);
438 if ("true".equals(xs)) {
439
440 return Boolean.TRUE;
441 }
442 if (!acceptNonQuote)
443 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
444
445 return xs;
446
447 case 'N':
448 readNQString(stop);
449 if (!acceptNaN)
450 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
451 if ("NaN".equals(xs)) {
452
453 return Float.valueOf(Float.NaN);
454 }
455 if (!acceptNonQuote)
456 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
457
458 return xs;
459
460 case '0':
461 case '1':
462 case '2':
463 case '3':
464 case '4':
465 case '5':
466 case '6':
467 case '7':
468 case '8':
469 case '9':
470 case '-':
471
472
473 return readNumber(stop);
474 default:
475 readNQString(stop);
476 if (!acceptNonQuote)
477 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
478
479 return xs;
480 }
481 }
482 }
483
484 abstract protected void readNoEnd() throws ParseException, IOException;
485
486 abstract protected void readNQString(boolean[] stop) throws IOException;
487
488 abstract protected Object readNumber(boolean[] stop) throws ParseException, IOException;
489
490 protected <T> T readObject(JsonReaderI<T> mapper) throws ParseException, IOException {
491
492 if (c != '{')
493 throw new RuntimeException("Internal Error");
494 Object current = mapper.createObject();
495 boolean needData = false;
496 boolean acceptData = true;
497 for (;;) {
498 read();
499 switch (c) {
500 case ' ':
501 case '\r':
502 case '\t':
503 case '\n':
504 continue;
505 case ':':
506 case ']':
507 case '[':
508 case '{':
509 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
510 case '}':
511 if (needData && !acceptUselessComma)
512 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
513 read();
514
515 return mapper.convert(current);
516 case ',':
517 if (needData && !acceptUselessComma)
518 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
519 acceptData = needData = true;
520 continue;
521 case '"':
522 case '\'':
523 default:
524
525 if (c == '\"' || c == '\'') {
526 readString();
527 } else {
528 readNQString(stopKey);
529 if (!acceptNonQuote)
530 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
531 }
532 String key = xs;
533 if (!acceptData)
534 throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, key);
535
536
537 skipSpace();
538
539 if (c != ':') {
540 if (c == EOI)
541 throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
542 throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, c);
543 }
544 readNoEnd();
545 lastKey = key;
546 Object value = readMain(mapper, stopValue);
547 mapper.setValue(current, key, value);
548 lastKey = null;
549
550
551
552
553
554
555 skipSpace();
556 if (c == '}') {
557 read();
558
559 return mapper.convert(current);
560 }
561 if (c == EOI)
562 throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
563
564 if (c == ',')
565 acceptData = needData = true;
566 else
567 throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c);
568
569 }
570 }
571 }
572
573
576 abstract void readS() throws IOException;
577
578 abstract protected void readString() throws ParseException, IOException;
579
580 protected void readString2() throws ParseException, IOException {
581
582 char sep = c;
583 for (;;) {
584 read();
585 switch (c) {
586 case EOI:
587 throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
588 case '"':
589 case '\'':
590 if (sep == c) {
591 read();
592 xs = sb.toString();
593 return;
594 }
595 sb.append(c);
596 break;
597 case '\\':
598 read();
599 switch (c) {
600 case 't':
601 sb.append('\t');
602 break;
603 case 'n':
604 sb.append('\n');
605 break;
606 case 'r':
607 sb.append('\r');
608 break;
609 case 'f':
610 sb.append('\f');
611 break;
612 case 'b':
613 sb.append('\b');
614 break;
615 case '\\':
616 sb.append('\\');
617 break;
618 case '/':
619 sb.append('/');
620 break;
621 case '\'':
622 sb.append('\'');
623 break;
624 case '"':
625 sb.append('"');
626 break;
627 case 'u':
628 sb.append(readUnicode(4));
629 break;
630 case 'x':
631 sb.append(readUnicode(2));
632 break;
633 default:
634 break;
635 }
636 break;
637 case '\0':
638 case (char) 1:
639 case (char) 2:
640 case (char) 3:
641 case (char) 4:
642 case (char) 5:
643 case (char) 6:
644 case (char) 7:
645 case '\b':
646 case '\t':
647 case '\n':
648 case (char) 11:
649 case '\f':
650 case '\r':
651 case (char) 14:
652 case (char) 15:
653 case (char) 16:
654 case (char) 17:
655 case (char) 18:
656 case (char) 19:
657 case (char) 20:
658 case (char) 21:
659 case (char) 22:
660 case (char) 23:
661 case (char) 24:
662 case (char) 25:
663
664 case (char) 27:
665 case (char) 28:
666 case (char) 29:
667 case (char) 30:
668 case (char) 31:
669 if (ignoreControlChar)
670 continue;
671 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
672 case (char) 127:
673 if (ignoreControlChar)
674 continue;
675 if (reject127)
676 throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
677 default:
678 sb.append(c);
679 }
680 }
681 }
682
683 protected char readUnicode(int totalChars) throws ParseException, IOException {
684 int value = 0;
685 for (int i = 0; i < totalChars; i++) {
686 value = value * 16;
687 read();
688 if (c <= '9' && c >= '0')
689 value += c - '0';
690 else if (c <= 'F' && c >= 'A')
691 value += (c - 'A') + 10;
692 else if (c >= 'a' && c <= 'f')
693 value += (c - 'a') + 10;
694 else if (c == EOI)
695 throw new ParseException(pos, ERROR_UNEXPECTED_EOF, "EOF");
696 else
697 throw new ParseException(pos, ERROR_UNEXPECTED_UNICODE, c);
698 }
699 return (char) value;
700 }
701
702 protected void skipDigits() throws IOException {
703 for (;;) {
704 if (c < '0' || c > '9')
705 return;
706 readS();
707 }
708 }
709
710 protected void skipNQString(boolean[] stop) throws IOException {
711 for (;;) {
712 if ((c == EOI) || (c >= 0 && c < MAX_STOP && stop[c]))
713 return;
714 readS();
715 }
716 }
717
718 protected void skipSpace() throws IOException {
719 for (;;) {
720 if (c > ' ' || c == EOI)
721 return;
722 readS();
723 }
724 }
725
726 public static class MSB {
727 char b[];
728 int p;
729
730 public MSB(int size) {
731 b = new char[size];
732 p = -1;
733 }
734
735 public void append(char c) {
736 p++;
737 if (b.length <= p) {
738 char[] t = new char[b.length * 2 + 1];
739 System.arraycopy(b, 0, t, 0, b.length);
740 b = t;
741 }
742 b[p] = c;
743 }
744
745 public void append(int c) {
746 p++;
747 if (b.length <= p) {
748 char[] t = new char[b.length * 2 + 1];
749 System.arraycopy(b, 0, t, 0, b.length);
750 b = t;
751 }
752 b[p] = (char) c;
753 }
754
755 public String toString() {
756 return new String(b, 0, p + 1);
757 }
758
759 public void clear() {
760 p = -1;
761 }
762 }
763 }
764