/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java

https://github.com/alibaba/fastjson · Java · 1655 lines · 1500 code · 118 blank · 37 comment · 191 complexity · 45138a622e29189f258784728b7ec1fa MD5 · raw file

  1. /*
  2. * Copyright 1999-2019 Alibaba Group.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.fastjson.parser;
  17. import java.io.Closeable;
  18. import java.math.BigDecimal;
  19. import java.math.BigInteger;
  20. import java.math.MathContext;
  21. import java.util.*;
  22. import com.alibaba.fastjson.JSON;
  23. import com.alibaba.fastjson.JSONException;
  24. import com.alibaba.fastjson.util.IOUtils;
  25. import static com.alibaba.fastjson.parser.JSONToken.*;
  26. import static com.alibaba.fastjson.util.TypeUtils.fnv1a_64_magic_hashcode;
  27. import static com.alibaba.fastjson.util.TypeUtils.fnv1a_64_magic_prime;
  28. /**
  29. * @author wenshao[szujobs@hotmail.com]
  30. */
  31. public abstract class JSONLexerBase implements JSONLexer, Closeable {
  32. protected void lexError(String key, Object... args) {
  33. token = ERROR;
  34. }
  35. protected int token;
  36. protected int pos;
  37. protected int features;
  38. protected char ch;
  39. protected int bp;
  40. protected int eofPos;
  41. /**
  42. * A character buffer for literals.
  43. */
  44. protected char[] sbuf;
  45. protected int sp;
  46. /**
  47. * number start position
  48. */
  49. protected int np;
  50. protected boolean hasSpecial;
  51. protected Calendar calendar = null;
  52. protected TimeZone timeZone = JSON.defaultTimeZone;
  53. protected Locale locale = JSON.defaultLocale;
  54. public int matchStat = UNKNOWN;
  55. private final static ThreadLocal<char[]> SBUF_LOCAL = new ThreadLocal<char[]>();
  56. protected String stringDefaultValue = null;
  57. protected int nanos = 0;
  58. public JSONLexerBase(int features){
  59. this.features = features;
  60. if ((features & Feature.InitStringFieldAsEmpty.mask) != 0) {
  61. stringDefaultValue = "";
  62. }
  63. sbuf = SBUF_LOCAL.get();
  64. if (sbuf == null) {
  65. sbuf = new char[512];
  66. }
  67. }
  68. public final int matchStat() {
  69. return matchStat;
  70. }
  71. /**
  72. * internal method, don't invoke
  73. * @param token
  74. */
  75. public void setToken(int token) {
  76. this.token = token;
  77. }
  78. public final void nextToken() {
  79. sp = 0;
  80. for (;;) {
  81. pos = bp;
  82. if (ch == '/') {
  83. skipComment();
  84. continue;
  85. }
  86. if (ch == '"') {
  87. scanString();
  88. return;
  89. }
  90. if (ch == ',') {
  91. next();
  92. token = COMMA;
  93. return;
  94. }
  95. if (ch >= '0' && ch <= '9') {
  96. scanNumber();
  97. return;
  98. }
  99. if (ch == '-') {
  100. scanNumber();
  101. return;
  102. }
  103. switch (ch) {
  104. case '\'':
  105. if (!isEnabled(Feature.AllowSingleQuotes)) {
  106. throw new JSONException("Feature.AllowSingleQuotes is false");
  107. }
  108. scanStringSingleQuote();
  109. return;
  110. case ' ':
  111. case '\t':
  112. case '\b':
  113. case '\f':
  114. case '\n':
  115. case '\r':
  116. next();
  117. break;
  118. case 't': // true
  119. scanTrue();
  120. return;
  121. case 'f': // false
  122. scanFalse();
  123. return;
  124. case 'n': // new,null
  125. scanNullOrNew();
  126. return;
  127. case 'T':
  128. case 'N': // NULL
  129. case 'S':
  130. case 'u': // undefined
  131. scanIdent();
  132. return;
  133. case '(':
  134. next();
  135. token = LPAREN;
  136. return;
  137. case ')':
  138. next();
  139. token = RPAREN;
  140. return;
  141. case '[':
  142. next();
  143. token = LBRACKET;
  144. return;
  145. case ']':
  146. next();
  147. token = RBRACKET;
  148. return;
  149. case '{':
  150. next();
  151. token = LBRACE;
  152. return;
  153. case '}':
  154. next();
  155. token = RBRACE;
  156. return;
  157. case ':':
  158. next();
  159. token = COLON;
  160. return;
  161. case ';':
  162. next();
  163. token = SEMI;
  164. return;
  165. case '.':
  166. next();
  167. token = DOT;
  168. return;
  169. case '+':
  170. next();
  171. scanNumber();
  172. return;
  173. case 'x':
  174. scanHex();
  175. return;
  176. default:
  177. if (isEOF()) { // JLS
  178. if (token == EOF) {
  179. throw new JSONException("EOF error");
  180. }
  181. token = EOF;
  182. eofPos = pos = bp;
  183. } else {
  184. if (ch <= 31 || ch == 127) {
  185. next();
  186. break;
  187. }
  188. lexError("illegal.char", String.valueOf((int) ch));
  189. next();
  190. }
  191. return;
  192. }
  193. }
  194. }
  195. public final void nextToken(int expect) {
  196. sp = 0;
  197. for (;;) {
  198. switch (expect) {
  199. case JSONToken.LBRACE:
  200. if (ch == '{') {
  201. token = JSONToken.LBRACE;
  202. next();
  203. return;
  204. }
  205. if (ch == '[') {
  206. token = JSONToken.LBRACKET;
  207. next();
  208. return;
  209. }
  210. break;
  211. case JSONToken.COMMA:
  212. if (ch == ',') {
  213. token = JSONToken.COMMA;
  214. next();
  215. return;
  216. }
  217. if (ch == '}') {
  218. token = JSONToken.RBRACE;
  219. next();
  220. return;
  221. }
  222. if (ch == ']') {
  223. token = JSONToken.RBRACKET;
  224. next();
  225. return;
  226. }
  227. if (ch == EOI) {
  228. token = JSONToken.EOF;
  229. return;
  230. }
  231. if (ch == 'n') {
  232. scanNullOrNew(false);
  233. return;
  234. }
  235. break;
  236. case JSONToken.LITERAL_INT:
  237. if (ch >= '0' && ch <= '9') {
  238. pos = bp;
  239. scanNumber();
  240. return;
  241. }
  242. if (ch == '"') {
  243. pos = bp;
  244. scanString();
  245. return;
  246. }
  247. if (ch == '[') {
  248. token = JSONToken.LBRACKET;
  249. next();
  250. return;
  251. }
  252. if (ch == '{') {
  253. token = JSONToken.LBRACE;
  254. next();
  255. return;
  256. }
  257. break;
  258. case JSONToken.LITERAL_STRING:
  259. if (ch == '"') {
  260. pos = bp;
  261. scanString();
  262. return;
  263. }
  264. if (ch >= '0' && ch <= '9') {
  265. pos = bp;
  266. scanNumber();
  267. return;
  268. }
  269. if (ch == '[') {
  270. token = JSONToken.LBRACKET;
  271. next();
  272. return;
  273. }
  274. if (ch == '{') {
  275. token = JSONToken.LBRACE;
  276. next();
  277. return;
  278. }
  279. break;
  280. case JSONToken.LBRACKET:
  281. if (ch == '[') {
  282. token = JSONToken.LBRACKET;
  283. next();
  284. return;
  285. }
  286. if (ch == '{') {
  287. token = JSONToken.LBRACE;
  288. next();
  289. return;
  290. }
  291. break;
  292. case JSONToken.RBRACKET:
  293. if (ch == ']') {
  294. token = JSONToken.RBRACKET;
  295. next();
  296. return;
  297. }
  298. case JSONToken.EOF:
  299. if (ch == EOI) {
  300. token = JSONToken.EOF;
  301. return;
  302. }
  303. break;
  304. case JSONToken.IDENTIFIER:
  305. nextIdent();
  306. return;
  307. default:
  308. break;
  309. }
  310. if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\b') {
  311. next();
  312. continue;
  313. }
  314. nextToken();
  315. break;
  316. }
  317. }
  318. public final void nextIdent() {
  319. while (isWhitespace(ch)) {
  320. next();
  321. }
  322. if (ch == '_' || ch == '$' || Character.isLetter(ch)) {
  323. scanIdent();
  324. } else {
  325. nextToken();
  326. }
  327. }
  328. public final void nextTokenWithColon() {
  329. nextTokenWithChar(':');
  330. }
  331. public final void nextTokenWithChar(char expect) {
  332. sp = 0;
  333. for (;;) {
  334. if (ch == expect) {
  335. next();
  336. nextToken();
  337. return;
  338. }
  339. if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\b') {
  340. next();
  341. continue;
  342. }
  343. throw new JSONException("not match " + expect + " - " + ch + ", info : " + this.info());
  344. }
  345. }
  346. public final int token() {
  347. return token;
  348. }
  349. public final String tokenName() {
  350. return JSONToken.name(token);
  351. }
  352. public final int pos() {
  353. return pos;
  354. }
  355. public final String stringDefaultValue() {
  356. return stringDefaultValue;
  357. }
  358. public final Number integerValue() throws NumberFormatException {
  359. long result = 0;
  360. boolean negative = false;
  361. if (np == -1) {
  362. np = 0;
  363. }
  364. int i = np, max = np + sp;
  365. long limit;
  366. long multmin;
  367. int digit;
  368. char type = ' ';
  369. switch (charAt(max - 1)) {
  370. case 'L':
  371. max--;
  372. type = 'L';
  373. break;
  374. case 'S':
  375. max--;
  376. type = 'S';
  377. break;
  378. case 'B':
  379. max--;
  380. type = 'B';
  381. break;
  382. default:
  383. break;
  384. }
  385. if (charAt(np) == '-') {
  386. negative = true;
  387. limit = Long.MIN_VALUE;
  388. i++;
  389. } else {
  390. limit = -Long.MAX_VALUE;
  391. }
  392. multmin = MULTMIN_RADIX_TEN;
  393. if (i < max) {
  394. digit = charAt(i++) - '0';
  395. result = -digit;
  396. }
  397. while (i < max) {
  398. // Accumulating negatively avoids surprises near MAX_VALUE
  399. digit = charAt(i++) - '0';
  400. if (result < multmin) {
  401. return new BigInteger(numberString(), 10);
  402. }
  403. result *= 10;
  404. if (result < limit + digit) {
  405. return new BigInteger(numberString(), 10);
  406. }
  407. result -= digit;
  408. }
  409. if (negative) {
  410. if (i > np + 1) {
  411. if (result >= Integer.MIN_VALUE && type != 'L') {
  412. if (type == 'S') {
  413. return (short) result;
  414. }
  415. if (type == 'B') {
  416. return (byte) result;
  417. }
  418. return (int) result;
  419. }
  420. return result;
  421. } else { /* Only got "-" */
  422. throw new JSONException("illegal number format : " + numberString());
  423. }
  424. } else {
  425. result = -result;
  426. if (result <= Integer.MAX_VALUE && type != 'L') {
  427. if (type == 'S') {
  428. return (short) result;
  429. }
  430. if (type == 'B') {
  431. return (byte) result;
  432. }
  433. return (int) result;
  434. }
  435. return result;
  436. }
  437. }
  438. public final void nextTokenWithColon(int expect) {
  439. nextTokenWithChar(':');
  440. }
  441. public float floatValue() {
  442. String strVal = numberString();
  443. float floatValue = Float.parseFloat(strVal);
  444. if (floatValue == 0 || floatValue == Float.POSITIVE_INFINITY) {
  445. char c0 = strVal.charAt(0);
  446. if (c0 > '0' && c0 <= '9') {
  447. throw new JSONException("float overflow : " + strVal);
  448. }
  449. }
  450. return floatValue;
  451. }
  452. public double doubleValue() {
  453. return Double.parseDouble(numberString());
  454. }
  455. public void config(Feature feature, boolean state) {
  456. features = Feature.config(features, feature, state);
  457. if ((features & Feature.InitStringFieldAsEmpty.mask) != 0) {
  458. stringDefaultValue = "";
  459. }
  460. }
  461. public final boolean isEnabled(Feature feature) {
  462. return isEnabled(feature.mask);
  463. }
  464. public final boolean isEnabled(int feature) {
  465. return (this.features & feature) != 0;
  466. }
  467. public final boolean isEnabled(int features, int feature) {
  468. return (this.features & feature) != 0 || (features & feature) != 0;
  469. }
  470. public abstract String numberString();
  471. public abstract boolean isEOF();
  472. public final char getCurrent() {
  473. return ch;
  474. }
  475. public abstract char charAt(int index);
  476. // public final char next() {
  477. // ch = doNext();
  478. //// if (ch == '/' && (this.features & Feature.AllowComment.mask) != 0) {
  479. //// skipComment();
  480. //// }
  481. // return ch;
  482. // }
  483. public abstract char next();
  484. protected void skipComment() {
  485. next();
  486. if (ch == '/') {
  487. for (;;) {
  488. next();
  489. if (ch == '\n') {
  490. next();
  491. return;
  492. } else if (ch == EOI) {
  493. return;
  494. }
  495. }
  496. } else if (ch == '*') {
  497. next();
  498. for (; ch != EOI;) {
  499. if (ch == '*') {
  500. next();
  501. if (ch == '/') {
  502. next();
  503. return;
  504. } else {
  505. continue;
  506. }
  507. }
  508. next();
  509. }
  510. } else {
  511. throw new JSONException("invalid comment");
  512. }
  513. }
  514. public final String scanSymbol(final SymbolTable symbolTable) {
  515. skipWhitespace();
  516. if (ch == '"') {
  517. return scanSymbol(symbolTable, '"');
  518. }
  519. if (ch == '\'') {
  520. if (!isEnabled(Feature.AllowSingleQuotes)) {
  521. throw new JSONException("syntax error");
  522. }
  523. return scanSymbol(symbolTable, '\'');
  524. }
  525. if (ch == '}') {
  526. next();
  527. token = JSONToken.RBRACE;
  528. return null;
  529. }
  530. if (ch == ',') {
  531. next();
  532. token = JSONToken.COMMA;
  533. return null;
  534. }
  535. if (ch == EOI) {
  536. token = JSONToken.EOF;
  537. return null;
  538. }
  539. if (!isEnabled(Feature.AllowUnQuotedFieldNames)) {
  540. throw new JSONException("syntax error");
  541. }
  542. return scanSymbolUnQuoted(symbolTable);
  543. }
  544. // public abstract String scanSymbol(final SymbolTable symbolTable, final char quote);
  545. protected abstract void arrayCopy(int srcPos, char[] dest, int destPos, int length);
  546. public final String scanSymbol(final SymbolTable symbolTable, final char quote) {
  547. int hash = 0;
  548. np = bp;
  549. sp = 0;
  550. boolean hasSpecial = false;
  551. char chLocal;
  552. for (;;) {
  553. chLocal = next();
  554. if (chLocal == quote) {
  555. break;
  556. }
  557. if (chLocal == EOI) {
  558. throw new JSONException("unclosed.str");
  559. }
  560. if (chLocal == '\\') {
  561. if (!hasSpecial) {
  562. hasSpecial = true;
  563. if (sp >= sbuf.length) {
  564. int newCapcity = sbuf.length * 2;
  565. if (sp > newCapcity) {
  566. newCapcity = sp;
  567. }
  568. char[] newsbuf = new char[newCapcity];
  569. System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
  570. sbuf = newsbuf;
  571. }
  572. // text.getChars(np + 1, np + 1 + sp, sbuf, 0);
  573. // System.arraycopy(this.buf, np + 1, sbuf, 0, sp);
  574. arrayCopy(np + 1, sbuf, 0, sp);
  575. }
  576. chLocal = next();
  577. switch (chLocal) {
  578. case '0':
  579. hash = 31 * hash + (int) chLocal;
  580. putChar('\0');
  581. break;
  582. case '1':
  583. hash = 31 * hash + (int) chLocal;
  584. putChar('\1');
  585. break;
  586. case '2':
  587. hash = 31 * hash + (int) chLocal;
  588. putChar('\2');
  589. break;
  590. case '3':
  591. hash = 31 * hash + (int) chLocal;
  592. putChar('\3');
  593. break;
  594. case '4':
  595. hash = 31 * hash + (int) chLocal;
  596. putChar('\4');
  597. break;
  598. case '5':
  599. hash = 31 * hash + (int) chLocal;
  600. putChar('\5');
  601. break;
  602. case '6':
  603. hash = 31 * hash + (int) chLocal;
  604. putChar('\6');
  605. break;
  606. case '7':
  607. hash = 31 * hash + (int) chLocal;
  608. putChar('\7');
  609. break;
  610. case 'b': // 8
  611. hash = 31 * hash + (int) '\b';
  612. putChar('\b');
  613. break;
  614. case 't': // 9
  615. hash = 31 * hash + (int) '\t';
  616. putChar('\t');
  617. break;
  618. case 'n': // 10
  619. hash = 31 * hash + (int) '\n';
  620. putChar('\n');
  621. break;
  622. case 'v': // 11
  623. hash = 31 * hash + (int) '\u000B';
  624. putChar('\u000B');
  625. break;
  626. case 'f': // 12
  627. case 'F':
  628. hash = 31 * hash + (int) '\f';
  629. putChar('\f');
  630. break;
  631. case 'r': // 13
  632. hash = 31 * hash + (int) '\r';
  633. putChar('\r');
  634. break;
  635. case '"': // 34
  636. hash = 31 * hash + (int) '"';
  637. putChar('"');
  638. break;
  639. case '\'': // 39
  640. hash = 31 * hash + (int) '\'';
  641. putChar('\'');
  642. break;
  643. case '/': // 47
  644. hash = 31 * hash + (int) '/';
  645. putChar('/');
  646. break;
  647. case '\\': // 92
  648. hash = 31 * hash + (int) '\\';
  649. putChar('\\');
  650. break;
  651. case 'x':
  652. char x1 = ch = next();
  653. char x2 = ch = next();
  654. int x_val = digits[x1] * 16 + digits[x2];
  655. char x_char = (char) x_val;
  656. hash = 31 * hash + (int) x_char;
  657. putChar(x_char);
  658. break;
  659. case 'u':
  660. char c1 = chLocal = next();
  661. char c2 = chLocal = next();
  662. char c3 = chLocal = next();
  663. char c4 = chLocal = next();
  664. int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16);
  665. hash = 31 * hash + val;
  666. putChar((char) val);
  667. break;
  668. default:
  669. this.ch = chLocal;
  670. throw new JSONException("unclosed.str.lit");
  671. }
  672. continue;
  673. }
  674. hash = 31 * hash + chLocal;
  675. if (!hasSpecial) {
  676. sp++;
  677. continue;
  678. }
  679. if (sp == sbuf.length) {
  680. putChar(chLocal);
  681. } else {
  682. sbuf[sp++] = chLocal;
  683. }
  684. }
  685. token = LITERAL_STRING;
  686. String value;
  687. if (!hasSpecial) {
  688. // return this.text.substring(np + 1, np + 1 + sp).intern();
  689. int offset;
  690. if (np == -1) {
  691. offset = 0;
  692. } else {
  693. offset = np + 1;
  694. }
  695. value = addSymbol(offset, sp, hash, symbolTable);
  696. } else {
  697. value = symbolTable.addSymbol(sbuf, 0, sp, hash);
  698. }
  699. sp = 0;
  700. this.next();
  701. return value;
  702. }
  703. public final void resetStringPosition() {
  704. this.sp = 0;
  705. }
  706. public String info() {
  707. return "";
  708. }
  709. public final String scanSymbolUnQuoted(final SymbolTable symbolTable) {
  710. if (token == JSONToken.ERROR && pos == 0 && bp == 1) {
  711. bp = 0; // adjust
  712. }
  713. final boolean[] firstIdentifierFlags = IOUtils.firstIdentifierFlags;
  714. final char first = ch;
  715. final boolean firstFlag = ch >= firstIdentifierFlags.length || firstIdentifierFlags[first];
  716. if (!firstFlag) {
  717. throw new JSONException("illegal identifier : " + ch //
  718. + info());
  719. }
  720. final boolean[] identifierFlags = IOUtils.identifierFlags;
  721. int hash = first;
  722. np = bp;
  723. sp = 1;
  724. char chLocal;
  725. for (;;) {
  726. chLocal = next();
  727. if (chLocal < identifierFlags.length) {
  728. if (!identifierFlags[chLocal]) {
  729. break;
  730. }
  731. }
  732. hash = 31 * hash + chLocal;
  733. sp++;
  734. continue;
  735. }
  736. this.ch = charAt(bp);
  737. token = JSONToken.IDENTIFIER;
  738. final int NULL_HASH = 3392903;
  739. if (sp == 4 && hash == NULL_HASH && charAt(np) == 'n' && charAt(np + 1) == 'u' && charAt(np + 2) == 'l'
  740. && charAt(np + 3) == 'l') {
  741. return null;
  742. }
  743. // return text.substring(np, np + sp).intern();
  744. if (symbolTable == null) {
  745. return subString(np, sp);
  746. }
  747. return this.addSymbol(np, sp, hash, symbolTable);
  748. // return symbolTable.addSymbol(buf, np, sp, hash);
  749. }
  750. protected abstract void copyTo(int offset, int count, char[] dest);
  751. public final void scanString() {
  752. np = bp;
  753. hasSpecial = false;
  754. char ch;
  755. for (;;) {
  756. ch = next();
  757. if (ch == '\"') {
  758. break;
  759. }
  760. if (ch == EOI) {
  761. if (!isEOF()) {
  762. putChar((char) EOI);
  763. continue;
  764. }
  765. throw new JSONException("unclosed string : " + ch);
  766. }
  767. if (ch == '\\') {
  768. if (!hasSpecial) {
  769. hasSpecial = true;
  770. if (sp >= sbuf.length) {
  771. int newCapcity = sbuf.length * 2;
  772. if (sp > newCapcity) {
  773. newCapcity = sp;
  774. }
  775. char[] newsbuf = new char[newCapcity];
  776. System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
  777. sbuf = newsbuf;
  778. }
  779. copyTo(np + 1, sp, sbuf);
  780. // text.getChars(np + 1, np + 1 + sp, sbuf, 0);
  781. // System.arraycopy(buf, np + 1, sbuf, 0, sp);
  782. }
  783. ch = next();
  784. switch (ch) {
  785. case '0':
  786. putChar('\0');
  787. break;
  788. case '1':
  789. putChar('\1');
  790. break;
  791. case '2':
  792. putChar('\2');
  793. break;
  794. case '3':
  795. putChar('\3');
  796. break;
  797. case '4':
  798. putChar('\4');
  799. break;
  800. case '5':
  801. putChar('\5');
  802. break;
  803. case '6':
  804. putChar('\6');
  805. break;
  806. case '7':
  807. putChar('\7');
  808. break;
  809. case 'b': // 8
  810. putChar('\b');
  811. break;
  812. case 't': // 9
  813. putChar('\t');
  814. break;
  815. case 'n': // 10
  816. putChar('\n');
  817. break;
  818. case 'v': // 11
  819. putChar('\u000B');
  820. break;
  821. case 'f': // 12
  822. case 'F':
  823. putChar('\f');
  824. break;
  825. case 'r': // 13
  826. putChar('\r');
  827. break;
  828. case '"': // 34
  829. putChar('"');
  830. break;
  831. case '\'': // 39
  832. putChar('\'');
  833. break;
  834. case '/': // 47
  835. putChar('/');
  836. break;
  837. case '\\': // 92
  838. putChar('\\');
  839. break;
  840. case 'x':
  841. char x1 = next();
  842. char x2 = next();
  843. boolean hex1 = (x1 >= '0' && x1 <= '9')
  844. || (x1 >= 'a' && x1 <= 'f')
  845. || (x1 >= 'A' && x1 <= 'F');
  846. boolean hex2 = (x2 >= '0' && x2 <= '9')
  847. || (x2 >= 'a' && x2 <= 'f')
  848. || (x2 >= 'A' && x2 <= 'F');
  849. if (!hex1 || !hex2) {
  850. throw new JSONException("invalid escape character \\x" + x1 + x2);
  851. }
  852. char x_char = (char) (digits[x1] * 16 + digits[x2]);
  853. putChar(x_char);
  854. break;
  855. case 'u':
  856. char u1 = next();
  857. char u2 = next();
  858. char u3 = next();
  859. char u4 = next();
  860. int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16);
  861. putChar((char) val);
  862. break;
  863. default:
  864. this.ch = ch;
  865. throw new JSONException("unclosed string : " + ch);
  866. }
  867. continue;
  868. }
  869. if (!hasSpecial) {
  870. sp++;
  871. continue;
  872. }
  873. if (sp == sbuf.length) {
  874. putChar(ch);
  875. } else {
  876. sbuf[sp++] = ch;
  877. }
  878. }
  879. token = JSONToken.LITERAL_STRING;
  880. this.ch = next();
  881. }
  882. public Calendar getCalendar() {
  883. return this.calendar;
  884. }
  885. public TimeZone getTimeZone() {
  886. return timeZone;
  887. }
  888. public void setTimeZone(TimeZone timeZone) {
  889. this.timeZone = timeZone;
  890. }
  891. public Locale getLocale() {
  892. return locale;
  893. }
  894. public void setLocale(Locale locale) {
  895. this.locale = locale;
  896. }
  897. public final int intValue() {
  898. if (np == -1) {
  899. np = 0;
  900. }
  901. int result = 0;
  902. boolean negative = false;
  903. int i = np, max = np + sp;
  904. int limit;
  905. int digit;
  906. if (charAt(np) == '-') {
  907. negative = true;
  908. limit = Integer.MIN_VALUE;
  909. i++;
  910. } else {
  911. limit = -Integer.MAX_VALUE;
  912. }
  913. long multmin = INT_MULTMIN_RADIX_TEN;
  914. if (i < max) {
  915. digit = charAt(i++) - '0';
  916. result = -digit;
  917. }
  918. while (i < max) {
  919. // Accumulating negatively avoids surprises near MAX_VALUE
  920. char chLocal = charAt(i++);
  921. if (chLocal == 'L' || chLocal == 'S' || chLocal == 'B') {
  922. break;
  923. }
  924. digit = chLocal - '0';
  925. if (result < multmin) {
  926. throw new NumberFormatException(numberString());
  927. }
  928. result *= 10;
  929. if (result < limit + digit) {
  930. throw new NumberFormatException(numberString());
  931. }
  932. result -= digit;
  933. }
  934. if (negative) {
  935. if (i > np + 1) {
  936. return result;
  937. } else { /* Only got "-" */
  938. throw new NumberFormatException(numberString());
  939. }
  940. } else {
  941. return -result;
  942. }
  943. }
  944. public abstract byte[] bytesValue();
  945. public void close() {
  946. if (sbuf.length <= 1024 * 8) {
  947. SBUF_LOCAL.set(sbuf);
  948. }
  949. this.sbuf = null;
  950. }
  951. public final boolean isRef() {
  952. if (sp != 4) {
  953. return false;
  954. }
  955. return charAt(np + 1) == '$' //
  956. && charAt(np + 2) == 'r' //
  957. && charAt(np + 3) == 'e' //
  958. && charAt(np + 4) == 'f';
  959. }
  960. public String scanTypeName(SymbolTable symbolTable) {
  961. return null;
  962. }
  963. protected final static char[] typeFieldName = ("\"" + JSON.DEFAULT_TYPE_KEY + "\":\"").toCharArray();
  964. public final int scanType(String type) {
  965. matchStat = UNKNOWN;
  966. if (!charArrayCompare(typeFieldName)) {
  967. return NOT_MATCH_NAME;
  968. }
  969. int bpLocal = this.bp + typeFieldName.length;
  970. final int typeLength = type.length();
  971. for (int i = 0; i < typeLength; ++i) {
  972. if (type.charAt(i) != charAt(bpLocal + i)) {
  973. return NOT_MATCH;
  974. }
  975. }
  976. bpLocal += typeLength;
  977. if (charAt(bpLocal) != '"') {
  978. return NOT_MATCH;
  979. }
  980. this.ch = charAt(++bpLocal);
  981. if (ch == ',') {
  982. this.ch = charAt(++bpLocal);
  983. this.bp = bpLocal;
  984. token = JSONToken.COMMA;
  985. return VALUE;
  986. } else if (ch == '}') {
  987. ch = charAt(++bpLocal);
  988. if (ch == ',') {
  989. token = JSONToken.COMMA;
  990. this.ch = charAt(++bpLocal);
  991. } else if (ch == ']') {
  992. token = JSONToken.RBRACKET;
  993. this.ch = charAt(++bpLocal);
  994. } else if (ch == '}') {
  995. token = JSONToken.RBRACE;
  996. this.ch = charAt(++bpLocal);
  997. } else if (ch == EOI) {
  998. token = JSONToken.EOF;
  999. } else {
  1000. return NOT_MATCH;
  1001. }
  1002. matchStat = END;
  1003. }
  1004. this.bp = bpLocal;
  1005. return matchStat;
  1006. }
  1007. public final boolean matchField(char[] fieldName) {
  1008. for (;;) {
  1009. if (!charArrayCompare(fieldName)) {
  1010. if (isWhitespace(ch)) {
  1011. next();
  1012. continue;
  1013. }
  1014. return false;
  1015. } else {
  1016. break;
  1017. }
  1018. }
  1019. bp = bp + fieldName.length;
  1020. ch = charAt(bp);
  1021. if (ch == '{') {
  1022. next();
  1023. token = JSONToken.LBRACE;
  1024. } else if (ch == '[') {
  1025. next();
  1026. token = JSONToken.LBRACKET;
  1027. } else if (ch == 'S' && charAt(bp + 1) == 'e' && charAt(bp + 2) == 't' && charAt(bp + 3) == '[') {
  1028. bp += 3;
  1029. ch = charAt(bp);
  1030. token = JSONToken.SET;
  1031. } else {
  1032. nextToken();
  1033. }
  1034. return true;
  1035. }
  1036. public int matchField(long fieldNameHash) {
  1037. throw new UnsupportedOperationException();
  1038. }
  1039. public boolean seekArrayToItem(int index) {
  1040. throw new UnsupportedOperationException();
  1041. }
  1042. public int seekObjectToField(long fieldNameHash, boolean deepScan) {
  1043. throw new UnsupportedOperationException();
  1044. }
  1045. public int seekObjectToField(long[] fieldNameHash) {
  1046. throw new UnsupportedOperationException();
  1047. }
  1048. public int seekObjectToFieldDeepScan(long fieldNameHash) {
  1049. throw new UnsupportedOperationException();
  1050. }
  1051. public void skipObject() {
  1052. throw new UnsupportedOperationException();
  1053. }
  1054. public void skipObject(boolean valid) {
  1055. throw new UnsupportedOperationException();
  1056. }
  1057. public void skipArray() {
  1058. throw new UnsupportedOperationException();
  1059. }
  1060. public abstract int indexOf(char ch, int startIndex);
  1061. public abstract String addSymbol(int offset, int len, int hash, final SymbolTable symbolTable);
  1062. public String scanFieldString(char[] fieldName) {
  1063. matchStat = UNKNOWN;
  1064. if (!charArrayCompare(fieldName)) {
  1065. matchStat = NOT_MATCH_NAME;
  1066. return stringDefaultValue();
  1067. }
  1068. // int index = bp + fieldName.length;
  1069. int offset = fieldName.length;
  1070. char chLocal = charAt(bp + (offset++));
  1071. if (chLocal != '"') {
  1072. matchStat = NOT_MATCH;
  1073. return stringDefaultValue();
  1074. }
  1075. final String strVal;
  1076. {
  1077. int startIndex = bp + fieldName.length + 1;
  1078. int endIndex = indexOf('"', startIndex);
  1079. if (endIndex == -1) {
  1080. throw new JSONException("unclosed str");
  1081. }
  1082. int startIndex2 = bp + fieldName.length + 1; // must re compute
  1083. String stringVal = subString(startIndex2, endIndex - startIndex2);
  1084. if (stringVal.indexOf('\\') != -1) {
  1085. for (;;) {
  1086. int slashCount = 0;
  1087. for (int i = endIndex - 1; i >= 0; --i) {
  1088. if (charAt(i) == '\\') {
  1089. slashCount++;
  1090. } else {
  1091. break;
  1092. }
  1093. }
  1094. if (slashCount % 2 == 0) {
  1095. break;
  1096. }
  1097. endIndex = indexOf('"', endIndex + 1);
  1098. }
  1099. int chars_len = endIndex - (bp + fieldName.length + 1);
  1100. char[] chars = sub_chars( bp + fieldName.length + 1, chars_len);
  1101. stringVal = readString(chars, chars_len);
  1102. }
  1103. offset += (endIndex - (bp + fieldName.length + 1) + 1);
  1104. chLocal = charAt(bp + (offset++));
  1105. strVal = stringVal;
  1106. }
  1107. if (chLocal == ',') {
  1108. bp += offset;
  1109. this.ch = this.charAt(bp);
  1110. matchStat = VALUE;
  1111. return strVal;
  1112. }
  1113. if (chLocal == '}') {
  1114. chLocal = charAt(bp + (offset++));
  1115. if (chLocal == ',') {
  1116. token = JSONToken.COMMA;
  1117. bp += offset;
  1118. this.ch = this.charAt(bp);
  1119. } else if (chLocal == ']') {
  1120. token = JSONToken.RBRACKET;
  1121. bp += offset;
  1122. this.ch = this.charAt(bp);
  1123. } else if (chLocal == '}') {
  1124. token = JSONToken.RBRACE;
  1125. bp += offset;
  1126. this.ch = this.charAt(bp);
  1127. } else if (chLocal == EOI) {
  1128. token = JSONToken.EOF;
  1129. bp += (offset - 1);
  1130. ch = EOI;
  1131. } else {
  1132. matchStat = NOT_MATCH;
  1133. return stringDefaultValue();
  1134. }
  1135. matchStat = END;
  1136. } else {
  1137. matchStat = NOT_MATCH;
  1138. return stringDefaultValue();
  1139. }
  1140. return strVal;
  1141. }
  1142. public String scanString(char expectNextChar) {
  1143. matchStat = UNKNOWN;
  1144. int offset = 0;
  1145. char chLocal = charAt(bp + (offset++));
  1146. if (chLocal == 'n') {
  1147. if (charAt(bp + offset) == 'u' && charAt(bp + offset + 1) == 'l' && charAt(bp + offset + 2) == 'l') {
  1148. offset += 3;
  1149. chLocal = charAt(bp + (offset++));
  1150. } else {
  1151. matchStat = NOT_MATCH;
  1152. return null;
  1153. }
  1154. if (chLocal == expectNextChar) {
  1155. bp += offset;
  1156. this.ch = this.charAt(bp);
  1157. matchStat = VALUE;
  1158. return null;
  1159. } else {
  1160. matchStat = NOT_MATCH;
  1161. return null;
  1162. }
  1163. }
  1164. final String strVal;
  1165. for (;;) {
  1166. if (chLocal == '"') {
  1167. int startIndex = bp + offset;
  1168. int endIndex = indexOf('"', startIndex);
  1169. if (endIndex == -1) {
  1170. throw new JSONException("unclosed str");
  1171. }
  1172. String stringVal = subString(bp + offset, endIndex - startIndex);
  1173. if (stringVal.indexOf('\\') != -1) {
  1174. for (; ; ) {
  1175. int slashCount = 0;
  1176. for (int i = endIndex - 1; i >= 0; --i) {
  1177. if (charAt(i) == '\\') {
  1178. slashCount++;
  1179. } else {
  1180. break;
  1181. }
  1182. }
  1183. if (slashCount % 2 == 0) {
  1184. break;
  1185. }
  1186. endIndex = indexOf('"', endIndex + 1);
  1187. }
  1188. int chars_len = endIndex - startIndex;
  1189. char[] chars = sub_chars(bp + 1, chars_len);
  1190. stringVal = readString(chars, chars_len);
  1191. }
  1192. offset += (endIndex - startIndex + 1);
  1193. chLocal = charAt(bp + (offset++));
  1194. strVal = stringVal;
  1195. break;
  1196. } else if (isWhitespace(chLocal)) {
  1197. chLocal = charAt(bp + (offset++));
  1198. continue;
  1199. } else {
  1200. matchStat = NOT_MATCH;
  1201. return stringDefaultValue();
  1202. }
  1203. }
  1204. for (;;) {
  1205. if (chLocal == expectNextChar) {
  1206. bp += offset;
  1207. this.ch = charAt(bp);
  1208. matchStat = VALUE;
  1209. token = JSONToken.COMMA;
  1210. return strVal;
  1211. } else if (isWhitespace(chLocal)) {
  1212. chLocal = charAt(bp + (offset++));
  1213. continue;
  1214. } else {
  1215. if (chLocal == ']') {
  1216. bp += offset;
  1217. this.ch = charAt(bp);
  1218. matchStat = NOT_MATCH;
  1219. }
  1220. return strVal;
  1221. }
  1222. }
  1223. }
  1224. public long scanFieldSymbol(char[] fieldName) {
  1225. matchStat = UNKNOWN;
  1226. if (!charArrayCompare(fieldName)) {
  1227. matchStat = NOT_MATCH_NAME;
  1228. return 0;
  1229. }
  1230. int offset = fieldName.length;
  1231. char chLocal = charAt(bp + (offset++));
  1232. if (chLocal != '"') {
  1233. matchStat = NOT_MATCH;
  1234. return 0;
  1235. }
  1236. long hash = fnv1a_64_magic_hashcode;
  1237. for (;;) {
  1238. chLocal = charAt(bp + (offset++));
  1239. if (chLocal == '\"') {
  1240. chLocal = charAt(bp + (offset++));
  1241. break;
  1242. }
  1243. hash ^= chLocal;
  1244. hash *= fnv1a_64_magic_prime;
  1245. if (chLocal == '\\') {
  1246. matchStat = NOT_MATCH;
  1247. return 0;
  1248. }
  1249. }
  1250. if (chLocal == ',') {
  1251. bp += offset;
  1252. this.ch = this.charAt(bp);
  1253. matchStat = VALUE;
  1254. return hash;
  1255. }
  1256. if (chLocal == '}') {
  1257. chLocal = charAt(bp + (offset++));
  1258. if (chLocal == ',') {
  1259. token = JSONToken.COMMA;
  1260. bp += offset;
  1261. this.ch = this.charAt(bp);
  1262. } else if (chLocal == ']') {
  1263. token = JSONToken.RBRACKET;
  1264. bp += offset;
  1265. this.ch = this.charAt(bp);
  1266. } else if (chLocal == '}') {
  1267. token = JSONToken.RBRACE;
  1268. bp += offset;
  1269. this.ch = this.charAt(bp);
  1270. } else if (chLocal == EOI) {
  1271. token = JSONToken.EOF;
  1272. bp += (offset - 1);
  1273. ch = EOI;
  1274. } else {
  1275. matchStat = NOT_MATCH;
  1276. return 0;
  1277. }
  1278. matchStat = END;
  1279. } else {
  1280. matchStat = NOT_MATCH;
  1281. return 0;
  1282. }
  1283. return hash;
  1284. }
  1285. public long scanEnumSymbol(char[] fieldName) {
  1286. matchStat = UNKNOWN;
  1287. if (!charArrayCompare(fieldName)) {
  1288. matchStat = NOT_MATCH_NAME;
  1289. return 0;
  1290. }
  1291. int offset = fieldName.length;
  1292. char chLocal = charAt(bp + (offset++));
  1293. if (chLocal != '"') {
  1294. matchStat = NOT_MATCH;
  1295. return 0;
  1296. }
  1297. long hash = fnv1a_64_magic_hashcode;
  1298. for (;;) {
  1299. chLocal = charAt(bp + (offset++));
  1300. if (chLocal == '\"') {
  1301. chLocal = charAt(bp + (offset++));
  1302. break;
  1303. }
  1304. hash ^= ((chLocal >= 'A' && chLocal <= 'Z') ? (chLocal + 32) : chLocal);
  1305. hash *= fnv1a_64_magic_prime;
  1306. if (chLocal == '\\') {
  1307. matchStat = NOT_MATCH;
  1308. return 0;
  1309. }
  1310. }
  1311. if (chLocal == ',') {
  1312. bp += offset;
  1313. this.ch = this.charAt(bp);
  1314. matchStat = VALUE;
  1315. return hash;
  1316. }
  1317. if (chLocal == '}') {
  1318. chLocal = charAt(bp + (offset++));
  1319. if (chLocal == ',') {
  1320. token = JSONToken.COMMA;
  1321. bp += offset;
  1322. this.ch = this.charAt(bp);
  1323. } else if (chLocal == ']') {
  1324. token = JSONToken.RBRACKET;
  1325. bp += offset;
  1326. this.ch = this.charAt(bp);
  1327. } else if (chLocal == '}') {
  1328. token = JSONToken.RBRACE;
  1329. bp += offset;
  1330. this.ch = this.charAt(bp);
  1331. } else if (chLocal == EOI) {
  1332. token = JSONToken.EOF;
  1333. bp += (offset - 1);
  1334. ch = EOI;
  1335. } else {
  1336. matchStat = NOT_MATCH;
  1337. return 0;
  1338. }
  1339. matchStat = END;
  1340. } else {
  1341. matchStat = NOT_MATCH;
  1342. return 0;
  1343. }
  1344. return hash;
  1345. }
  1346. @SuppressWarnings({ "unchecked", "rawtypes" })
  1347. public Enum<?> scanEnum(Class<?> enumClass, final SymbolTable symbolTable, char serperator) {
  1348. String name = scanSymbolWithSeperator(symbolTable, serperator);
  1349. if (name == null) {
  1350. return null;
  1351. }
  1352. return Enum.valueOf((Class<? extends Enum>) enumClass, name);
  1353. }
  1354. public String scanSymbolWithSeperator(final SymbolTable symbolTable, char serperator) {
  1355. matchStat = UNKNOWN;
  1356. int offset = 0;
  1357. char chLocal = charAt(bp + (offset++));
  1358. if (chLocal == 'n') {
  1359. if (charAt(bp + offset) == 'u' && charAt(bp + offset + 1) == 'l' && charAt(bp + offset + 2) == 'l') {
  1360. offset += 3;
  1361. chLocal = charAt(bp + (offset++));
  1362. } else {
  1363. matchStat = NOT_MATCH;
  1364. return null;
  1365. }
  1366. if (chLocal == serperator) {
  1367. bp += offset;
  1368. this.ch = this.charAt(bp);
  1369. matchStat = VALUE;
  1370. return null;
  1371. } else {
  1372. matchStat = NOT_MATCH;
  1373. return null;
  1374. }
  1375. }
  1376. if (chLocal != '"') {
  1377. matchStat = NOT_MATCH;
  1378. return null;
  1379. }
  1380. String strVal;
  1381. // int start = index;
  1382. int hash = 0;
  1383. for (;;) {
  1384. chLocal = charAt(bp + (offset++));
  1385. if (chLocal == '\"') {
  1386. // bp = index;
  1387. // this.ch = chLocal = charAt(bp);
  1388. int start = bp + 0 + 1;
  1389. int len = bp + offset - start - 1;
  1390. strVal = addSymbol(start, len, hash, symbolTable);
  1391. chLocal = charAt(bp + (offset++));
  1392. break;
  1393. }
  1394. hash = 31 * hash + chLocal;
  1395. if (chLocal == '\\') {
  1396. matchStat = NOT_MATCH;
  1397. return null;
  1398. }
  1399. }
  1400. for (;;) {
  1401. if (chLocal == serperator) {
  1402. bp += offset;
  1403. this.ch = this.charAt(bp);
  1404. matchStat = VALUE;
  1405. return strVal;
  1406. } else {
  1407. if (isWhitespace(chLocal)) {
  1408. chLocal = charAt(bp + (offset++));
  1409. continue;
  1410. }
  1411. matchStat = NOT_MATCH;
  1412. return strVal;
  1413. }
  1414. }
  1415. }
  1416. public Collection<String> newCollectionByType(Class<?> type){
  1417. if (type.isAssignableFrom(HashSet.class)) {