bson/src/main/org/bson/json/JsonScanner.java
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);
            }
        }

    }
CHECKSTYLE:OFF