private JsonToken scanNumber(final char firstChar) {

        int c = firstChar;
        StringBuilder sb = new StringBuilder();
        sb.append(firstChar);

        NumberState state;

        switch (c) {
            case '-':
                state = NumberState.SAW_LEADING_MINUS;
                break;
            case '0':
                state = NumberState.SAW_LEADING_ZERO;
                break;
            default:
                state = NumberState.SAW_INTEGER_DIGITS;
                break;
        }

        JsonTokenType type = JsonTokenType.INT64;


        while (true) {
            c = buffer.read();
            switch (state) {
                case SAW_LEADING_MINUS:
                    switch (c) {
                        case '0':
                            state = NumberState.SAW_LEADING_ZERO;
                            break;
                        case 'I':
                            state = NumberState.SAW_MINUS_I;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_LEADING_ZERO:
                    switch (c) {
                        case '.':
                            state = NumberState.SAW_DECIMAL_POINT;
                            break;
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_INTEGER_DIGITS:
                    switch (c) {
                        case '.':
                            state = NumberState.SAW_DECIMAL_POINT;
                            break;
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_DECIMAL_POINT:
                    type = JsonTokenType.DOUBLE;
                    if (Character.isDigit(c)) {
                        state = NumberState.SAW_FRACTION_DIGITS;
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                case SAW_FRACTION_DIGITS:
                    switch (c) {
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_FRACTION_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_EXPONENT_LETTER:
                    type = JsonTokenType.DOUBLE;
                    switch (c) {
                        case '+':
                        case '-':
                            state = NumberState.SAW_EXPONENT_SIGN;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_EXPONENT_DIGITS;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_EXPONENT_SIGN:
                    if (Character.isDigit(c)) {
                        state = NumberState.SAW_EXPONENT_DIGITS;
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                case SAW_EXPONENT_DIGITS:
                    switch (c) {
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_EXPONENT_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_MINUS_I:
                    boolean sawMinusInfinity = true;
                    char[] nfinity = new char[]{'n', 'f', 'i', 'n', 'i', 't', 'y'};
                    for (int i = 0; i < nfinity.length; i++) {
                        if (c != nfinity[i]) {
                            sawMinusInfinity = false;
                            break;
                        }
                        sb.append((char) c);
                        c = buffer.read();
                    }
                    if (sawMinusInfinity) {
                        type = JsonTokenType.DOUBLE;
                        switch (c) {
                            case ',':
                            case '}':
                            case ']':
                            case ')':
                            case -1:
                                state = NumberState.DONE;
                                break;
                            default:
                                if (Character.isWhitespace(c)) {
                                    state = NumberState.DONE;
                                } else {
                                    state = NumberState.INVALID;
                                }
                                break;
                        }
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                default:
            }

            switch (state) {
                case INVALID:
                    throw new JsonParseException("Invalid JSON number");
                case DONE:
                    buffer.unread(c);
                    String lexeme = sb.toString();
                    if (type == JsonTokenType.DOUBLE) {
                        return new JsonToken(JsonTokenType.DOUBLE, Double.parseDouble(lexeme));
                    } else {
                        long value = Long.parseLong(lexeme);
                        if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
                            return new JsonToken(JsonTokenType.INT64, value);
                        } else {
                            return new JsonToken(JsonTokenType.INT32, (int) value);
                        }
                    }
                default:
                    sb.append((char) c);
            }
        }

    }
private JsonToken scanNumber(final char firstChar) {

        int c = firstChar;
        StringBuilder sb = new StringBuilder();
        sb.append(firstChar);

        NumberState state;

        switch (c) {
            case '-':
                state = NumberState.SAW_LEADING_MINUS;
                break;
            case '0':
                state = NumberState.SAW_LEADING_ZERO;
                break;
            default:
                state = NumberState.SAW_INTEGER_DIGITS;
                break;
        }

        JsonTokenType type = JsonTokenType.INT64;


        while (true) {
            c = buffer.read();
            switch (state) {
                case SAW_LEADING_MINUS:
                    switch (c) {
                        case '0':
                            state = NumberState.SAW_LEADING_ZERO;
                            break;
                        case 'I':
                            state = NumberState.SAW_MINUS_I;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_LEADING_ZERO:
                    switch (c) {
                        case '.':
                            state = NumberState.SAW_DECIMAL_POINT;
                            break;
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_INTEGER_DIGITS:
                    switch (c) {
                        case '.':
                            state = NumberState.SAW_DECIMAL_POINT;
                            break;
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_INTEGER_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_DECIMAL_POINT:
                    type = JsonTokenType.DOUBLE;
                    if (Character.isDigit(c)) {
                        state = NumberState.SAW_FRACTION_DIGITS;
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                case SAW_FRACTION_DIGITS:
                    switch (c) {
                        case 'e':
                        case 'E':
                            state = NumberState.SAW_EXPONENT_LETTER;
                            break;
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                        case -1:
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_FRACTION_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_EXPONENT_LETTER:
                    type = JsonTokenType.DOUBLE;
                    switch (c) {
                        case '+':
                        case '-':
                            state = NumberState.SAW_EXPONENT_SIGN;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_EXPONENT_DIGITS;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_EXPONENT_SIGN:
                    if (Character.isDigit(c)) {
                        state = NumberState.SAW_EXPONENT_DIGITS;
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                case SAW_EXPONENT_DIGITS:
                    switch (c) {
                        case ',':
                        case '}':
                        case ']':
                        case ')':
                            state = NumberState.DONE;
                            break;
                        default:
                            if (Character.isDigit(c)) {
                                state = NumberState.SAW_EXPONENT_DIGITS;
                            } else if (Character.isWhitespace(c)) {
                                state = NumberState.DONE;
                            } else {
                                state = NumberState.INVALID;
                            }
                            break;
                    }
                    break;
                case SAW_MINUS_I:
                    boolean sawMinusInfinity = true;
                    char[] nfinity = new char[]{'n', 'f', 'i', 'n', 'i', 't', 'y'};
                    for (int i = 0; i < nfinity.length; i++) {
                        if (c != nfinity[i]) {
                            sawMinusInfinity = false;
                            break;
                        }
                        sb.append((char) c);
                        c = buffer.read();
                    }
                    if (sawMinusInfinity) {
                        type = JsonTokenType.DOUBLE;
                        switch (c) {
                            case ',':
                            case '}':
                            case ']':
                            case ')':
                            case -1:
                                state = NumberState.DONE;
                                break;
                            default:
                                if (Character.isWhitespace(c)) {
                                    state = NumberState.DONE;
                                } else {
                                    state = NumberState.INVALID;
                                }
                                break;
                        }
                    } else {
                        state = NumberState.INVALID;
                    }
                    break;
                default:
            }

            switch (state) {
                case INVALID:
                    throw new JsonParseException("Invalid JSON number");
                case DONE:
                    buffer.unread(c);
                    String lexeme = sb.toString();
                    if (type == JsonTokenType.DOUBLE) {
                        return new JsonToken(JsonTokenType.DOUBLE, Double.parseDouble(lexeme));
                    } else {
                        long value = Long.parseLong(lexeme);
                        if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
                            return new JsonToken(JsonTokenType.INT64, value);
                        } else {
                            return new JsonToken(JsonTokenType.INT32, (int) value);
                        }
                    }
                default:
                    sb.append((char) c);
            }
        }

    }
private JsonToken scanNumber ( final char firstChar ) { int c = firstChar ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( firstChar ) ; NumberState state ; switch ( c ) { case ' ' : state = NumberState . SAW_LEADING_MINUS ; break ; case ' ' : state = NumberState . SAW_LEADING_ZERO ; break ; default : state = NumberState . SAW_INTEGER_DIGITS ; break ; } JsonTokenType type = JsonTokenType . INT64 ; while ( true ) { c = buffer . read ( ) ; switch ( state ) { case SAW_LEADING_MINUS : switch ( c ) { case ' ' : state = NumberState . SAW_LEADING_ZERO ; break ; case ' ' : state = NumberState . SAW_MINUS_I ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_INTEGER_DIGITS ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_LEADING_ZERO : switch ( c ) { case ' ' : state = NumberState . SAW_DECIMAL_POINT ; break ; case ' ' : case ' ' : state = NumberState . SAW_EXPONENT_LETTER ; break ; case ' ' : case ' ' : case ' ' : case ' ' : case - 1 : state = NumberState . DONE ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_INTEGER_DIGITS ; } else if ( Character . isWhitespace ( c ) ) { state = NumberState . DONE ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_INTEGER_DIGITS : switch ( c ) { case ' ' : state = NumberState . SAW_DECIMAL_POINT ; break ; case ' ' : case ' ' : state = NumberState . SAW_EXPONENT_LETTER ; break ; case ' ' : case ' ' : case ' ' : case ' ' : case - 1 : state = NumberState . DONE ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_INTEGER_DIGITS ; } else if ( Character . isWhitespace ( c ) ) { state = NumberState . DONE ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_DECIMAL_POINT : type = JsonTokenType . DOUBLE ; if ( Character . isDigit ( c ) ) { state = NumberState . SAW_FRACTION_DIGITS ; } else { state = NumberState . INVALID ; } break ; case SAW_FRACTION_DIGITS : switch ( c ) { case ' ' : case ' ' : state = NumberState . SAW_EXPONENT_LETTER ; break ; case ' ' : case ' ' : case ' ' : case ' ' : case - 1 : state = NumberState . DONE ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_FRACTION_DIGITS ; } else if ( Character . isWhitespace ( c ) ) { state = NumberState . DONE ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_EXPONENT_LETTER : type = JsonTokenType . DOUBLE ; switch ( c ) { case ' ' : case ' ' : state = NumberState . SAW_EXPONENT_SIGN ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_EXPONENT_DIGITS ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_EXPONENT_SIGN : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_EXPONENT_DIGITS ; } else { state = NumberState . INVALID ; } break ; case SAW_EXPONENT_DIGITS : switch ( c ) { case ' ' : case ' ' : case ' ' : case ' ' : state = NumberState . DONE ; break ; default : if ( Character . isDigit ( c ) ) { state = NumberState . SAW_EXPONENT_DIGITS ; } else if ( Character . isWhitespace ( c ) ) { state = NumberState . DONE ; } else { state = NumberState . INVALID ; } break ; } break ; case SAW_MINUS_I : boolean sawMinusInfinity = true ; char [ ] nfinity = new char [ ] { ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' } ; for ( int i = 0 ; i < nfinity . length ; i ++ ) { if ( c != nfinity [ i ] ) { sawMinusInfinity = false ; break ; } sb . append ( ( char ) c ) ; c = buffer . read ( ) ; } if ( sawMinusInfinity ) { type = JsonTokenType . DOUBLE ; switch ( c ) { case ' ' : case ' ' : case ' ' : case ' ' : case - 1 : state = NumberState . DONE ; break ; default : if ( Character . isWhitespace ( c ) ) { state = NumberState . DONE ; } else { state = NumberState . INVALID ; } break ; } } else { state = NumberState . INVALID ; } break ; default : } switch ( state ) { case INVALID : throw new JsonParseException ( "Invalid JSON number" ) ; case DONE : buffer . unread ( c ) ; String lexeme = sb . toString ( ) ; if ( type == JsonTokenType . DOUBLE ) { return new JsonToken ( JsonTokenType . DOUBLE , Double . parseDouble ( lexeme ) ) ; } else { long value = Long . parseLong ( lexeme ) ; if ( value < Integer . MIN_VALUE || value > Integer . MAX_VALUE ) { return new JsonToken ( JsonTokenType . INT64 , value ) ; } else { return new JsonToken ( JsonTokenType . INT32 , ( int ) value ) ; } } default : sb . append ( ( char ) c ) ; } } }
CHECKSTYLE:OFF
CHECKSTYLE : OFF