private JsonToken numericValue()

in cayenne/src/main/java/org/apache/cayenne/value/json/JsonTokenizer.java [213:349]


    private JsonToken numericValue() {
        checkValueState(data[position]);
        /*
         * number
         *     integer fraction exponent
         *
         * integer
         *     digit
         *     onenine digits
         *     '-' digit
         *     '-' onenine digits
         *
         * digits
         *     digit
         *     digit digits
         *
         * digit
         *     '0'
         *     onenine
         *
         * onenine
         *
         *
         * fraction
         *     ""
         *     '.' digits
         *
         * exponent
         *     ""
         *     'E' sign digits
         *     'e' sign digits
         *
         * sign
         *     ""
         *     '+'
         *     '-'
         */

        int startPosition = position;
        NumberState state = NumberState.NONE;

        while (state != NumberState.DONE) {
            switch (data[position]) {
                case '0':
                    if(state == NumberState.NONE
                            || state == NumberState.MINUS) {
                        state = NumberState.ZERO;
                    } else if(state == NumberState.EXPONENT) {
                        state = NumberState.EXP_SIGN;
                    } else if(state != NumberState.DIGITS
                            && state != NumberState.FRACTION
                            && state != NumberState.EXP_SIGN) {
                        throw new MalformedJsonException("Wrong number format at position " + position);
                    }
                    break;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    if(state == NumberState.NONE
                            || state == NumberState.MINUS) {
                        state = NumberState.DIGITS;
                    }
                    if(state == NumberState.EXPONENT) {
                        state = NumberState.EXP_SIGN;
                    }
                    break;
                case '-':
                    if(state == NumberState.NONE) {
                        state = NumberState.MINUS;
                    } else if(state == NumberState.EXPONENT) {
                        state = NumberState.EXP_SIGN;
                    } else {
                        throw new MalformedJsonException("Wrong number format at position " + position);
                    }
                    break;
                case '+':
                    if(state != NumberState.EXPONENT) {
                        throw new MalformedJsonException("Wrong number format at position " + position);
                    }
                    state = NumberState.EXP_SIGN;
                    break;
                case '.':
                    if(state != NumberState.ZERO
                            && state != NumberState.DIGITS) {
                        throw new MalformedJsonException("Wrong number format at position " + position);
                    }
                    state = NumberState.FRACTION;
                    break;
                case 'e':
                case 'E':
                    if(state != NumberState.NONE
                            && state != NumberState.ZERO
                            && state != NumberState.DIGITS
                            && state != NumberState.FRACTION) {
                        throw new MalformedJsonException("Wrong number format at position " + position);
                    }
                    state = NumberState.EXPONENT;
                    break;

                case '}':
                case ']':
                case ':':
                case ',':
                case ' ':
                case '\t':
                case '\f':
                case '\r':
                case '\n':
                    state = NumberState.DONE;
                    position--; // this char should be consumed by outer call
                    break;
                default:
                    throw new MalformedJsonException("Wrong number format at position " + position);
            }

            if(position >= data.length - 1) {
                if(state == NumberState.DIGITS
                        || state == NumberState.ZERO
                        || state == NumberState.FRACTION
                        || state == NumberState.EXP_SIGN) {
                    state = NumberState.DONE;
                }
                if(state != NumberState.DONE) {
                    throw new MalformedJsonException("Wrong number format at position " + position);
                }
            }
            position++;
        }

        return new JsonToken(TokenType.NUMBER, startPosition, position);
    }