content: package com.alipay.api.internal.util.json;
  
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.text.CharacterIterator;
  import java.text.StringCharacterIterator;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  /**
   * 不能直接使用JSONReader，请用JSONValidatingReader，所以这里改为abstract修饰。
   */
  public abstract class JSONReader {
  
      private static final Object OBJECT_END = new Object();
      private static final Object ARRAY_END  = new Object();
      private static final Object COLON      = new Object();
      private static final Object COMMA      = new Object();
      public static final  int    FIRST      = 0;
      public static final  int    CURRENT    = 1;
      public static final  int    NEXT       = 2;
  
      private static Map<Character, Character> escapes = new HashMap<Character, Character>();
  
      static {
          escapes.put(Character.valueOf('"'), Character.valueOf('"'));
          escapes.put(Character.valueOf('\\'), Character.valueOf('\\'));
          escapes.put(Character.valueOf('/'), Character.valueOf('/'));
          escapes.put(Character.valueOf('b'), Character.valueOf('\b'));
          escapes.put(Character.valueOf('f'), Character.valueOf('\f'));
          escapes.put(Character.valueOf('n'), Character.valueOf('\n'));
          escapes.put(Character.valueOf('r'), Character.valueOf('\r'));
          escapes.put(Character.valueOf('t'), Character.valueOf('\t'));
      }
  
      private CharacterIterator it;
      private char              c;
      private Object            token;
      private StringBuffer      buf = new StringBuffer();
  
      private char next() {
          c = it.next();
          return c;
      }
  
      private void skipWhiteSpace() {
          while (Character.isWhitespace(c)) {
              next();
          }
      }
  
      public Object read(CharacterIterator ci, int start) {
          it = ci;
          switch (start) {
              case FIRST:
                  c = it.first();
                  break;
              case CURRENT:
                  c = it.current();
                  break;
              case NEXT:
                  c = it.next();
                  break;
          }
          return read();
      }
  
      public Object read(CharacterIterator it) {
          return read(it, NEXT);
      }
  
      public Object read(String string) {
          return read(new StringCharacterIterator(string), FIRST);
      }
  
      private Object read() {
          skipWhiteSpace();
          char ch = c;
          next();
          switch (ch) {
              case '"':
                  token = string();
                  break;
              case '[':
                  token = array();
                  break;
              case ']':
                  token = ARRAY_END;
                  break;
              case ',':
                  token = COMMA;
                  break;
              case '{':
                  token = object();
                  break;
              case '}':
                  token = OBJECT_END;
                  break;
              case ':':
                  token = COLON;
                  break;
              case 't':
                  next();
                  next();
                  next(); // assumed r-u-e
                  token = Boolean.TRUE;
                  break;
              case 'f':
                  next();
                  next();
                  next();
                  next(); // assumed a-l-s-e
                  token = Boolean.FALSE;
                  break;
              case 'n':
                  next();
                  next();
                  next(); // assumed u-l-l
                  token = null;
                  break;
              default:
                  c = it.previous();
                  if (Character.isDigit(c) || c == '-') {
                      token = number();
                  }
          }
          // System.out.println("token: " + token); // enable this line to see the token stream
          return token;
      }
  
      private Object object() {
          Map<Object, Object> ret = new HashMap<Object, Object>();
          Object key = read();
          while (token != OBJECT_END) {
              read(); // should be a colon
              if (token != OBJECT_END) {
                  ret.put(key, read());
                  if (read() == COMMA) {
                      key = read();
                  }
              }
          }
  
          return ret;
      }
  
      private Object array() {
          List<Object> ret = new ArrayList<Object>();
          Object value = read();
          while (token != ARRAY_END) {
              ret.add(value);
              if (read() == COMMA) {
                  value = read();
              }
          }
          return ret;
      }
  
      private Object number() {
          int length = 0;
          boolean isFloatingPoint = false;
          buf.setLength(0);
  
          if (c == '-') {
              add();
          }
          length += addDigits();
          if (c == '.') {
              add();
              length += addDigits();
              isFloatingPoint = true;
          }
          if (c == 'e' || c == 'E') {
              add();
              if (c == '+' || c == '-') {
                  add();
              }
              addDigits();
              isFloatingPoint = true;
          }
  
          String s = buf.toString();
          return isFloatingPoint
                  ? (length < 17) ? (Object) Double.valueOf(s) : new BigDecimal(s)
                  : (length < 19) ? (Object) Long.valueOf(s) : new BigInteger(s);
      }
  
      private int addDigits() {
          int ret;
          for (ret = 0; Character.isDigit(c); ++ret) {
              add();
          }
          return ret;
      }
  
      private Object string() {
          buf.setLength(0);
          while (c != '"') {
              if (c == '\\') {
                  next();
                  if (c == 'u') {
                      add(unicode());
                  } else {
                      Object value = escapes.get(Character.valueOf(c));
                      if (value != null) {
                          add(((Character) value).charValue());
                      }
                  }
              } else {
                  add();
              }
          }
          next();
  
          return buf.toString();
      }
  
      private void add(char cc) {
          buf.append(cc);
          next();
      }
  
      private void add() {
          add(c);
      }
  
      private char unicode() {
          int value = 0;
          for (int i = 0; i < 4; ++i) {
              switch (next()) {
                  case '0':
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                      value = (value << 4) + c - '0';
                      break;
                  case 'a':
                  case 'b':
                  case 'c':
                  case 'd':
                  case 'e':
                  case 'f':
                      value = (value << 4) + c - 'k';
                      break;
                  case 'A':
                  case 'B':
                  case 'C':
                  case 'D':
                  case 'E':
                  case 'F':
                      value = (value << 4) + c - 'K';
                      break;
              }
          }
          return (char) value;
      }
  }