• JSONCkecker(Java语言版本)


    // MIT License
    //
    // Copyright (c) 2016 Michel Kraemer
    // Copyright (c) 2005 JSON.org
    //
    // Permission is hereby granted, free of charge, to any person obtaining
    // a copy of this software and associated documentation files (the
    // "Software"), to deal in the Software without restriction, including
    // without limitation the rights to use, copy, modify, merge, publish,
    // distribute, sublicense, and/or sell copies of the Software, and to
    // permit persons to whom the Software is furnished to do so, subject to
    // the following conditions:
    //
    // The above copyright notice and this permission notice shall be
    // included in all copies or substantial portions of the Software.
    //
    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    package de.undercouch.actson;
    
    /**
     * This class is based on the file
     * <a href="http://www.json.org/JSON_checker/">JSON_checker.c</a>
     * from <a href="http://www.json.org/">JSON.org</a>
     * @author Michel Kraemer
     * @author JSON.org
     */
    public class JsonChecker {
      private static final int __ = -1; // the universal error code
    
      /**
       * Characters are mapped into these 31 character classes. This allows for
       * a significant reduction in the size of the state transition table.
       */
      private static final int C_SPACE =  0;  // space
      private static final int C_WHITE =  1;  // other whitespace
      private static final int C_LCURB =  2;  // {
      private static final int C_RCURB =  3;  // }
      private static final int C_LSQRB =  4;  // [
      private static final int C_RSQRB =  5;  // ]
      private static final int C_COLON =  6;  // :
      private static final int C_COMMA =  7;  // ,
      private static final int C_QUOTE =  8;  // "
      private static final int C_BACKS =  9;  // 
      private static final int C_SLASH = 10;  // /
      private static final int C_PLUS  = 11;  // +
      private static final int C_MINUS = 12;  // -
      private static final int C_POINT = 13;  // .
      private static final int C_ZERO  = 14;  // 0
      private static final int C_DIGIT = 15;  // 123456789
      private static final int C_LOW_A = 16;  // a
      private static final int C_LOW_B = 17;  // b
      private static final int C_LOW_C = 18;  // c
      private static final int C_LOW_D = 19;  // d
      private static final int C_LOW_E = 20;  // e
      private static final int C_LOW_F = 21;  // f
      private static final int C_LOW_L = 22;  // l
      private static final int C_LOW_N = 23;  // n
      private static final int C_LOW_R = 24;  // r
      private static final int C_LOW_S = 25;  // s
      private static final int C_LOW_T = 26;  // t
      private static final int C_LOW_U = 27;  // u
      private static final int C_ABCDF = 28;  // ABCDF
      private static final int C_E     = 29;  // E
      private static final int C_ETC   = 30;  // everything else
    
      /**
       * This array maps the 128 ASCII characters into character classes.
       * The remaining Unicode characters should be mapped to C_ETC.
       * Non-whitespace control characters are errors.
       */
      private final static int[] ascii_class = {
        __,      __,      __,      __,      __,      __,      __,      __,
        __,      C_WHITE, C_WHITE, __,      __,      C_WHITE, __,      __,
        __,      __,      __,      __,      __,      __,      __,      __,
        __,      __,      __,      __,      __,      __,      __,      __,
    
        C_SPACE, C_ETC,   C_QUOTE, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_PLUS,  C_COMMA, C_MINUS, C_POINT, C_SLASH,
        C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
        C_DIGIT, C_DIGIT, C_COLON, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
    
        C_ETC,   C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_LSQRB, C_BACKS, C_RSQRB, C_ETC,   C_ETC,
    
        C_ETC,   C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_LOW_L, C_ETC,   C_LOW_N, C_ETC,
        C_ETC,   C_ETC,   C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC,   C_ETC,
        C_ETC,   C_ETC,   C_ETC,   C_LCURB, C_ETC,   C_RCURB, C_ETC,   C_ETC
      };
      
      /**
       * The state codes.
       */
      private static final int GO =  0;  // start
      private static final int OK =  1;  // ok
      private static final int OB =  2;  // object
      private static final int KE =  3;  // key
      private static final int CO =  4;  // colon
      private static final int VA =  5;  // value
      private static final int AR =  6;  // array
      private static final int ST =  7;  // string
      private static final int ES =  8;  // escape
      private static final int U1 =  9;  // u1
      private static final int U2 = 10;  // u2
      private static final int U3 = 11;  // u3
      private static final int U4 = 12;  // u4
      private static final int MI = 13;  // minus
      private static final int ZE = 14;  // zero
      private static final int IN = 15;  // integer
      private static final int FR = 16;  // fraction
      private static final int E1 = 17;  // e
      private static final int E2 = 18;  // ex
      private static final int E3 = 19;  // exp
      private static final int T1 = 20;  // tr
      private static final int T2 = 21;  // tru
      private static final int T3 = 22;  // true
      private static final int F1 = 23;  // fa
      private static final int F2 = 24;  // fal
      private static final int F3 = 25;  // fals
      private static final int F4 = 26;  // false
      private static final int N1 = 27;  // nu
      private static final int N2 = 28;  // nul
      private static final int N3 = 29;  // null
    
      /**
       * The state transition table takes the current state and the current symbol,
       * and returns either a new state or an action. An action is represented as a
       * negative number. A JSON text is accepted if at the end of the text the
       * state is OK and if the mode is MODE_DONE.
       */
      private static int[][] state_transition_table = {
      /*               white                                      1-9                                   ABCDF  etc
                   space |  {  }  [  ]  :  ,  "    /  +  -  .  0  |  a  b  c  d  e  f  l  n  r  s  t  u  |  E  |*/
      /*start  GO*/ {GO,GO,-6,__,-5,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*ok     OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*object OB*/ {OB,OB,__,-9,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*key    KE*/ {KE,KE,__,__,__,__,__,__,ST,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*colon  CO*/ {CO,CO,__,__,__,__,-2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*value  VA*/ {VA,VA,-6,__,-5,__,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
      /*array  AR*/ {AR,AR,-6,__,-5,-7,__,__,ST,__,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__},
      /*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,ES,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
      /*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__},
      /*u1     U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__},
      /*u2     U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__},
      /*u3     U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__},
      /*u4     U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ST,ST,ST,ST,ST,ST,ST,ST,__,__,__,__,__,__,ST,ST,__},
      /*minus  MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*zero   ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*int    IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
      /*frac   FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__},
      /*e      E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*ex     E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*exp    E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*tr     T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__},
      /*tru    T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__},
      /*true   T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
      /*fa     F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
      /*fal    F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__},
      /*fals   F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__},
      /*false  F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__},
      /*nu     N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__},
      /*nul    N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__},
      /*null   N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__},
      };
    
      /**
       * These modes can be pushed on the stack.
       */
      private static final int MODE_ARRAY  = 0;
      private static final int MODE_DONE   = 1;
      private static final int MODE_KEY    = 2;
      private static final int MODE_OBJECT = 3;
      
      /**
       * The stack containing the current modes
       */
      private int[] stack;
      
      /**
       * The top of the stack (-1 if the stack is empty)
       */
      private int top = -1;
      
      /**
       * The current state
       */
      private int state;
      
      /**
       * Push a mode onto the stack
       * @param mode the mode to push
       * @return false if there is overflow
       */
      private boolean push(int mode) {
        ++top;
        if (top >= stack.length) {
            return false;
        }
        stack[top] = mode;
        return true;
      }
      
      /**
       * Pop the stack, assuring that the current mode matches the expectation
       * @param mode the expected mode
       * @return false if there is underflow or if the modes mismatch
       */
      private boolean pop(int mode) {
        if (top < 0 || stack[top] != mode) {
          return false;
        }
        --top;
        return true;
      }
      
      /**
       * Constructs the JsonChecker
       */
      public JsonChecker() {
        this(16);
      }
    
      /**
       * Constructs the JsonChecker
       * @param depth the maximum number of nested states
       */
      public JsonChecker(int depth) {
        stack = new int[depth];
        top = -1;
        state = GO;
        push(MODE_DONE);
      }
    
      /**
       * Call this function for each character (or partial character) in your JSON text.
       * It can accept UTF-8, UTF-16, or UTF-32.
       * @param nextChar the character to feed
       * @return <code>true</code> if things are looking ok so far, <code>false</code>
       * if it rejects the text.
       */
      public boolean feed(char nextChar) {
        // Determine the character's class.
        int nextClass;
        if (nextChar < 0) {
            return false;
        }
        if (nextChar >= 128) {
            nextClass = C_ETC;
        } else {
            nextClass = ascii_class[nextChar];
            if (nextClass <= __) {
                return false;
            }
        }
        
        // Get the next state from the state transition table.
        int nextState = state_transition_table[state][nextClass];
        if (nextState >= 0) {
          // Change the state.
          state = nextState;
        } else {
          // Or perform one of the actions.
          switch (nextState) {
          // empty }
          case -9:
            if (!pop(MODE_KEY)) {
                return false;
            }
            state = OK;
            break;
    
          // }
          case -8:
            if (!pop(MODE_OBJECT)) {
                return false;
            }
            state = OK;
            break;
    
          // ]
          case -7:
            if (!pop(MODE_ARRAY)) {
                return false;
            }
            state = OK;
            break;
    
          // {
          case -6:
            if (!push(MODE_KEY)) {
                return false;
            }
            state = OB;
            break;
    
          // [
          case -5:
            if (!push(MODE_ARRAY)) {
                return false;
            }
            state = AR;
            break;
    
          // "
          case -4:
            switch (stack[top]) {
            case MODE_KEY:
              state = CO;
              break;
            case MODE_ARRAY:
            case MODE_OBJECT:
              state = OK;
              break;
            default:
              return false;
            }
            break;
    
          // ,
          case -3:
            switch (stack[top]) {
            case MODE_OBJECT:
              // A comma causes a flip from object mode to key mode.
              if (!pop(MODE_OBJECT) || !push(MODE_KEY)) {
                  return false;
              }
              state = KE;
              break;
            case MODE_ARRAY:
              state = VA;
              break;
            default:
              return false;
            }
            break;
    
          // :
          case -2:
            // A colon causes a flip from key mode to object mode.
            if (!pop(MODE_KEY) || !push(MODE_OBJECT)) {
              return false;
            }
            state = VA;
            break;
    
          // Bad action.
          default:
            return false;
          }
        }
        return true;
      }
    
      /**
       * This method should be called after all of the characters have been
       * processed, but only if every call to {@link #feed(char)} returned
       * <code>true</code>.
       * @return <code>true</code> if the JSON text was accepted.
       */
      public boolean done() {
        return state == OK && pop(MODE_DONE);
      }
    }
  • 相关阅读:
    双向链表

    一个简单makefile
    内存管理
    队列
    postgresql表结构查询sql
    postgresql 命令
    NSMutableDictionary 中使用setValueForKey 和 setObjectForKey有什么区别?
    ViewController 生命周期
    程序启动过程
  • 原文地址:https://www.cnblogs.com/felixzh/p/6381932.html
Copyright © 2020-2023  润新知